summaryrefslogtreecommitdiffstats
path: root/c/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-11-23 19:07:58 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-11-23 19:07:58 +0000
commit07a3253de2c3f9bc2d96a351680ec72548dadd2d (patch)
treeb4f85e78927202cffe01b194c708c3dd800d8e57 /c/src
parentAdded new tests in support of the file system infrastructure. (diff)
downloadrtems-07a3253de2c3f9bc2d96a351680ec72548dadd2d.tar.bz2
Added base version of file system infrastructure. This includes a major
overhaul of the RTEMS system call interface. This base file system is the "In-Memory File System" aka IMFS. The design and implementation was done by the following people: + Joel Sherrill (joel@OARcorp.com) + Jennifer Averett (jennifer@OARcorp.com) + Steve "Mr Mount" Salitasc (salitasc@OARcorp.com) + Kerwin Wade (wade@OARcorp.com) PROBLEMS ======== + It is VERY likely that merging this will break the UNIX port. This can/will be fixed. + There is likely some reentrancy/mutual exclusion needed. + Eventually, there should be a "mini-IMFS" description table to eliminate links, symlinks, etc to save memory. All you need to have "classic RTEMS" functionality is technically directories and device IO. All the rest could be left out to save memory.
Diffstat (limited to 'c/src')
-rw-r--r--c/src/exec/include/rtems/libio_.h248
-rw-r--r--c/src/exec/libcsupport/include/rtems/libio.h551
-rw-r--r--c/src/exec/libcsupport/include/rtems/libio_.h248
-rw-r--r--c/src/exec/libcsupport/src/CASES23
-rw-r--r--c/src/exec/libcsupport/src/TODO11
-rw-r--r--c/src/exec/libcsupport/src/__brk.c27
-rw-r--r--c/src/exec/libcsupport/src/__gettod.c19
-rw-r--r--c/src/exec/libcsupport/src/__sbrk.c29
-rw-r--r--c/src/exec/libcsupport/src/__times.c36
-rw-r--r--c/src/exec/libcsupport/src/access.c46
-rw-r--r--c/src/exec/libcsupport/src/base_fs.c81
-rw-r--r--c/src/exec/libcsupport/src/cfgetispeed.c29
-rw-r--r--c/src/exec/libcsupport/src/cfgetospeed.c29
-rw-r--r--c/src/exec/libcsupport/src/cfsetispeed.c36
-rw-r--r--c/src/exec/libcsupport/src/cfsetospeed.c36
-rw-r--r--c/src/exec/libcsupport/src/chdir.c50
-rw-r--r--c/src/exec/libcsupport/src/chmod.c40
-rw-r--r--c/src/exec/libcsupport/src/chown.c38
-rw-r--r--c/src/exec/libcsupport/src/close.c70
-rw-r--r--c/src/exec/libcsupport/src/closedir.c62
-rw-r--r--c/src/exec/libcsupport/src/dup.c23
-rw-r--r--c/src/exec/libcsupport/src/dup2.c49
-rw-r--r--c/src/exec/libcsupport/src/eval.c74
-rw-r--r--c/src/exec/libcsupport/src/fchmod.c50
-rw-r--r--c/src/exec/libcsupport/src/fcntl.c111
-rw-r--r--c/src/exec/libcsupport/src/fdatasync.c45
-rw-r--r--c/src/exec/libcsupport/src/fpathconf.c91
-rw-r--r--c/src/exec/libcsupport/src/fstat.c94
-rw-r--r--c/src/exec/libcsupport/src/fsync.c45
-rw-r--r--c/src/exec/libcsupport/src/ftruncate.c60
-rw-r--r--c/src/exec/libcsupport/src/getdents.c55
-rw-r--r--c/src/exec/libcsupport/src/hosterr.c27
-rw-r--r--c/src/exec/libcsupport/src/ioctl.c57
-rw-r--r--c/src/exec/libcsupport/src/libio.c663
-rw-r--r--c/src/exec/libcsupport/src/link.c60
-rw-r--r--c/src/exec/libcsupport/src/lseek.c93
-rw-r--r--c/src/exec/libcsupport/src/malloc.c14
-rw-r--r--c/src/exec/libcsupport/src/mkdir.c28
-rw-r--r--c/src/exec/libcsupport/src/mkfifo.c25
-rw-r--r--c/src/exec/libcsupport/src/mknod.c60
-rw-r--r--c/src/exec/libcsupport/src/mount.c299
-rw-r--r--c/src/exec/libcsupport/src/newlibc.c78
-rw-r--r--c/src/exec/libcsupport/src/no_libc.c20
-rw-r--r--c/src/exec/libcsupport/src/open.c202
-rw-r--r--c/src/exec/libcsupport/src/opendir.c78
-rw-r--r--c/src/exec/libcsupport/src/pathconf.c38
-rw-r--r--c/src/exec/libcsupport/src/pipe.c (renamed from c/src/lib/libc/_execve.c)14
-rw-r--r--c/src/exec/libcsupport/src/read.c84
-rw-r--r--c/src/exec/libcsupport/src/readdir.c75
-rw-r--r--c/src/exec/libcsupport/src/readlink.c43
-rw-r--r--c/src/exec/libcsupport/src/rewinddir.c21
-rw-r--r--c/src/exec/libcsupport/src/rmdir.c56
-rw-r--r--c/src/exec/libcsupport/src/scandir.c148
-rw-r--r--c/src/exec/libcsupport/src/seekdir.c27
-rw-r--r--c/src/exec/libcsupport/src/stat.c79
-rw-r--r--c/src/exec/libcsupport/src/symlink.c34
-rw-r--r--c/src/exec/libcsupport/src/tcdrain.c21
-rw-r--r--c/src/exec/libcsupport/src/tcgetattr.c33
-rw-r--r--c/src/exec/libcsupport/src/tcsetattr.c38
-rw-r--r--c/src/exec/libcsupport/src/telldir.c28
-rw-r--r--c/src/exec/libcsupport/src/truncate.c41
-rw-r--r--c/src/exec/libcsupport/src/umask.c30
-rw-r--r--c/src/exec/libcsupport/src/unixlibc.c10
-rw-r--r--c/src/exec/libcsupport/src/unlink.c44
-rw-r--r--c/src/exec/libcsupport/src/unmount.c214
-rw-r--r--c/src/exec/libcsupport/src/utime.c35
-rw-r--r--c/src/exec/libcsupport/src/write.c92
-rw-r--r--c/src/exec/libfs/src/imfs/deviceio.c215
-rw-r--r--c/src/exec/libfs/src/imfs/imfs.h445
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_chown.c52
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_creat.c130
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_debug.c160
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_directory.c278
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_eval.c638
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_fchmod.c55
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_free.c99
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_getchild.c68
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_gtkn.c84
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_init.c158
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_initsupp.c158
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_link.c72
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_mknod.c76
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_mount.c49
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_ntype.c29
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_readlink.c40
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_rmnod.c97
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_stat.c59
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_symlink.c60
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_unlink.c67
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_unmount.c58
-rw-r--r--c/src/exec/libfs/src/imfs/imfs_utime.c38
-rw-r--r--c/src/exec/libfs/src/imfs/ioman.c83
-rw-r--r--c/src/exec/libfs/src/imfs/memfile.c1000
-rw-r--r--c/src/exec/posix/include/sys/Makefile.in2
-rw-r--r--c/src/exec/posix/src/getpid.c19
-rw-r--r--c/src/exec/posix/src/psignal.c20
-rw-r--r--c/src/exec/posix/sys/Makefile.in2
-rw-r--r--c/src/exec/sapi/src/io.c4
-rw-r--r--c/src/lib/include/rtems/libio.h551
-rw-r--r--c/src/lib/include/rtems/libio_.h248
-rw-r--r--c/src/lib/libbsp/shared/bsplibc.c2
-rw-r--r--c/src/lib/libbsp/shared/bsppost.c6
-rw-r--r--c/src/lib/libc/CASES23
-rw-r--r--c/src/lib/libc/Makefile.in51
-rw-r--r--c/src/lib/libc/TODO11
-rw-r--r--c/src/lib/libc/__brk.c27
-rw-r--r--c/src/lib/libc/__gettod.c19
-rw-r--r--c/src/lib/libc/__sbrk.c29
-rw-r--r--c/src/lib/libc/__times.c36
-rw-r--r--c/src/lib/libc/access.c46
-rw-r--r--c/src/lib/libc/base_fs.c81
-rw-r--r--c/src/lib/libc/cfgetispeed.c29
-rw-r--r--c/src/lib/libc/cfgetospeed.c29
-rw-r--r--c/src/lib/libc/cfiospeed.c54
-rw-r--r--c/src/lib/libc/cfsetispeed.c36
-rw-r--r--c/src/lib/libc/cfsetospeed.c36
-rw-r--r--c/src/lib/libc/chdir.c50
-rw-r--r--c/src/lib/libc/chmod.c40
-rw-r--r--c/src/lib/libc/chown.c38
-rw-r--r--c/src/lib/libc/close.c70
-rw-r--r--c/src/lib/libc/closedir.c62
-rw-r--r--c/src/lib/libc/deviceio.c215
-rw-r--r--c/src/lib/libc/dup.c23
-rw-r--r--c/src/lib/libc/dup2.c49
-rw-r--r--c/src/lib/libc/eval.c74
-rw-r--r--c/src/lib/libc/fchmod.c50
-rw-r--r--c/src/lib/libc/fcntl.c111
-rw-r--r--c/src/lib/libc/fdatasync.c45
-rw-r--r--c/src/lib/libc/fpathconf.c91
-rw-r--r--c/src/lib/libc/fstat.c94
-rw-r--r--c/src/lib/libc/fsync.c45
-rw-r--r--c/src/lib/libc/ftruncate.c60
-rw-r--r--c/src/lib/libc/getdents.c55
-rw-r--r--c/src/lib/libc/hosterr.c27
-rw-r--r--c/src/lib/libc/imfs.h445
-rw-r--r--c/src/lib/libc/imfs_chown.c52
-rw-r--r--c/src/lib/libc/imfs_creat.c130
-rw-r--r--c/src/lib/libc/imfs_debug.c160
-rw-r--r--c/src/lib/libc/imfs_directory.c278
-rw-r--r--c/src/lib/libc/imfs_eval.c638
-rw-r--r--c/src/lib/libc/imfs_fchmod.c55
-rw-r--r--c/src/lib/libc/imfs_free.c99
-rw-r--r--c/src/lib/libc/imfs_getchild.c68
-rw-r--r--c/src/lib/libc/imfs_gtkn.c84
-rw-r--r--c/src/lib/libc/imfs_handlers.c93
-rw-r--r--c/src/lib/libc/imfs_init.c158
-rw-r--r--c/src/lib/libc/imfs_initsupp.c158
-rw-r--r--c/src/lib/libc/imfs_link.c72
-rw-r--r--c/src/lib/libc/imfs_mknod.c76
-rw-r--r--c/src/lib/libc/imfs_mount.c49
-rw-r--r--c/src/lib/libc/imfs_ntype.c29
-rw-r--r--c/src/lib/libc/imfs_readlink.c40
-rw-r--r--c/src/lib/libc/imfs_rmnod.c97
-rw-r--r--c/src/lib/libc/imfs_stat.c59
-rw-r--r--c/src/lib/libc/imfs_symlink.c60
-rw-r--r--c/src/lib/libc/imfs_unlink.c67
-rw-r--r--c/src/lib/libc/imfs_unmount.c58
-rw-r--r--c/src/lib/libc/imfs_utime.c38
-rw-r--r--c/src/lib/libc/internal.h41
-rw-r--r--c/src/lib/libc/ioctl.c57
-rw-r--r--c/src/lib/libc/ioman.c83
-rw-r--r--c/src/lib/libc/libio.c663
-rw-r--r--c/src/lib/libc/libio.h551
-rw-r--r--c/src/lib/libc/libio_.h248
-rw-r--r--c/src/lib/libc/link.c60
-rw-r--r--c/src/lib/libc/lseek.c93
-rw-r--r--c/src/lib/libc/malloc.c14
-rw-r--r--c/src/lib/libc/memfile.c1000
-rw-r--r--c/src/lib/libc/mkdir.c28
-rw-r--r--c/src/lib/libc/mkfifo.c25
-rw-r--r--c/src/lib/libc/mknod.c60
-rw-r--r--c/src/lib/libc/mount.c299
-rw-r--r--c/src/lib/libc/newlibc.c78
-rw-r--r--c/src/lib/libc/newlibif.c93
-rw-r--r--c/src/lib/libc/newlibifr.c103
-rw-r--r--c/src/lib/libc/no_libc.c20
-rw-r--r--c/src/lib/libc/open.c202
-rw-r--r--c/src/lib/libc/opendir.c78
-rw-r--r--c/src/lib/libc/pathconf.c38
-rw-r--r--c/src/lib/libc/pipe.c23
-rw-r--r--c/src/lib/libc/read.c84
-rw-r--r--c/src/lib/libc/readdir.c75
-rw-r--r--c/src/lib/libc/readlink.c43
-rw-r--r--c/src/lib/libc/rewinddir.c21
-rw-r--r--c/src/lib/libc/rmdir.c56
-rw-r--r--c/src/lib/libc/scandir.c148
-rw-r--r--c/src/lib/libc/seekdir.c27
-rw-r--r--c/src/lib/libc/stat.c79
-rw-r--r--c/src/lib/libc/support.c52
-rw-r--r--c/src/lib/libc/symlink.c34
-rw-r--r--c/src/lib/libc/syscalls.c99
-rw-r--r--c/src/lib/libc/tcattr.c40
-rw-r--r--c/src/lib/libc/tcdrain.c21
-rw-r--r--c/src/lib/libc/tcgetattr.c33
-rw-r--r--c/src/lib/libc/tcsetattr.c38
-rw-r--r--c/src/lib/libc/telldir.c28
-rw-r--r--c/src/lib/libc/truncate.c41
-rw-r--r--c/src/lib/libc/umask.c30
-rw-r--r--c/src/lib/libc/unixlibc.c10
-rw-r--r--c/src/lib/libc/unlink.c44
-rw-r--r--c/src/lib/libc/unmount.c214
-rw-r--r--c/src/lib/libc/utime.c35
-rw-r--r--c/src/lib/libc/write.c92
-rw-r--r--c/src/lib/libchip/serial/ns16550.c1
-rw-r--r--c/src/libchip/serial/ns16550.c1
-rw-r--r--c/src/libfs/src/imfs/deviceio.c215
-rw-r--r--c/src/libfs/src/imfs/imfs.h445
-rw-r--r--c/src/libfs/src/imfs/imfs_chown.c52
-rw-r--r--c/src/libfs/src/imfs/imfs_creat.c130
-rw-r--r--c/src/libfs/src/imfs/imfs_debug.c160
-rw-r--r--c/src/libfs/src/imfs/imfs_directory.c278
-rw-r--r--c/src/libfs/src/imfs/imfs_eval.c638
-rw-r--r--c/src/libfs/src/imfs/imfs_fchmod.c55
-rw-r--r--c/src/libfs/src/imfs/imfs_free.c99
-rw-r--r--c/src/libfs/src/imfs/imfs_getchild.c68
-rw-r--r--c/src/libfs/src/imfs/imfs_gtkn.c84
-rw-r--r--c/src/libfs/src/imfs/imfs_init.c158
-rw-r--r--c/src/libfs/src/imfs/imfs_initsupp.c158
-rw-r--r--c/src/libfs/src/imfs/imfs_link.c72
-rw-r--r--c/src/libfs/src/imfs/imfs_mknod.c76
-rw-r--r--c/src/libfs/src/imfs/imfs_mount.c49
-rw-r--r--c/src/libfs/src/imfs/imfs_ntype.c29
-rw-r--r--c/src/libfs/src/imfs/imfs_readlink.c40
-rw-r--r--c/src/libfs/src/imfs/imfs_rmnod.c97
-rw-r--r--c/src/libfs/src/imfs/imfs_stat.c59
-rw-r--r--c/src/libfs/src/imfs/imfs_symlink.c60
-rw-r--r--c/src/libfs/src/imfs/imfs_unlink.c67
-rw-r--r--c/src/libfs/src/imfs/imfs_unmount.c58
-rw-r--r--c/src/libfs/src/imfs/imfs_utime.c38
-rw-r--r--c/src/libfs/src/imfs/ioman.c83
-rw-r--r--c/src/libfs/src/imfs/memfile.c1000
-rw-r--r--c/src/tests/sptests/spsize/size.c22
232 files changed, 22837 insertions, 1862 deletions
diff --git a/c/src/exec/include/rtems/libio_.h b/c/src/exec/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/exec/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * 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$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.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 */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#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 rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/exec/libcsupport/include/rtems/libio.h b/c/src/exec/libcsupport/include/rtems/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/exec/libcsupport/include/rtems/libio.h
+++ b/c/src/exec/libcsupport/include/rtems/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * 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$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/exec/libcsupport/include/rtems/libio_.h b/c/src/exec/libcsupport/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/exec/libcsupport/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * 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$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.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 */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#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 rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/exec/libcsupport/src/CASES b/c/src/exec/libcsupport/src/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/c/src/exec/libcsupport/src/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/c/src/exec/libcsupport/src/TODO b/c/src/exec/libcsupport/src/TODO
new file mode 100644
index 0000000000..9d894688d9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/TODO
@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
diff --git a/c/src/exec/libcsupport/src/__brk.c b/c/src/exec/libcsupport/src/__brk.c
index 4dab22c729..24efa93adb 100644
--- a/c/src/exec/libcsupport/src/__brk.c
+++ b/c/src/exec/libcsupport/src/__brk.c
@@ -1,10 +1,7 @@
-#if !defined(RTEMS_UNIX)
-
/*
- * RTEMS "Broken" __brk/__sbrk Implementation
- *
- * NOTE: sbrk is BSP provided.
+ * RTEMS "Broken" __brk Implementation
*
+ * NOTE: sbrk() is provided by each BSP.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,27 +15,15 @@
*/
#include <rtems.h>
+#if !defined(RTEMS_UNIX)
-#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#ifdef RTEMS_NEWLIB
-#include <reent.h>
-#endif
-#include <unistd.h>
-
-/* we use RTEMS for memory management. We don't need sbrk */
-void * __sbrk(int incr)
-{
- errno = EINVAL;
- return (void *)0;
-}
-
-int __brk( const void *endds )
+int __brk(
+ const void *endds
+)
{
errno = EINVAL;
return -1;
}
-
#endif
diff --git a/c/src/exec/libcsupport/src/__gettod.c b/c/src/exec/libcsupport/src/__gettod.c
index dc83c47ce4..16857da870 100644
--- a/c/src/exec/libcsupport/src/__gettod.c
+++ b/c/src/exec/libcsupport/src/__gettod.c
@@ -1,11 +1,5 @@
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-
-#include <rtems.h>
-
-#if !defined(RTEMS_UNIX)
/*
- * RTEMS gettimeofday Implementation
- *
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,6 +12,11 @@
* $Id$
*/
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
#ifdef RTEMS_NEWLIB
#include <sys/reent.h>
#endif
@@ -61,7 +60,7 @@ int gettimeofday(
*
* NOTE: XXX this routine should really be in the executive proper.
*/
-
+
rtems_interrupt_disable(level);
seconds = _TOD_Seconds_since_epoch;
microseconds = _TOD_Current.ticks;
@@ -86,7 +85,7 @@ int gettimeofday(
return 0;
}
-#if defined(RTEMS_NEWLIB)
+#if defined(RTEMS_NEWLIB)
/*
* "Reentrant" version
@@ -102,7 +101,7 @@ int _gettimeofday_r(
}
/*
- * "System call" version
+ * "System call" version
*/
int _gettimeofday(
diff --git a/c/src/exec/libcsupport/src/__sbrk.c b/c/src/exec/libcsupport/src/__sbrk.c
new file mode 100644
index 0000000000..b1d31467fd
--- /dev/null
+++ b/c/src/exec/libcsupport/src/__sbrk.c
@@ -0,0 +1,29 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * 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>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/__times.c b/c/src/exec/libcsupport/src/__times.c
index 635bf8e062..5f7525ec5f 100644
--- a/c/src/exec/libcsupport/src/__times.c
+++ b/c/src/exec/libcsupport/src/__times.c
@@ -1,6 +1,5 @@
/*
- * RTEMS _times Implementation
- *
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -25,8 +24,8 @@ clock_t _times(
struct tms *ptms
)
{
- rtems_status_code status;
- rtems_interval ticks_since_boot;
+ rtems_status_code status;
+ rtems_interval ticks;
if ( !ptms ) {
errno = EFAULT;
@@ -34,21 +33,19 @@ clock_t _times(
}
/* "POSIX" does not seem to allow for not having a TOD */
- status = rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &ticks_since_boot
- );
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
if ( status != RTEMS_SUCCESSFUL ) {
assert( 0 );
return -1;
}
/*
- * RTEMS has no notion of system versus user time and does
- * not (as of 3.2.0) keep track of CPU usage on a per task basis.
+ * RTEMS has no notion of system versus user time and although
+ * a way to keep track of per task CPU usage was added since
+ * 3.6.0, this routine does not utilize it yet.
*/
- ptms->tms_utime = ticks_since_boot;
+ ptms->tms_utime = ticks;
ptms->tms_stime = 0;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
@@ -56,6 +53,12 @@ clock_t _times(
return 0;
}
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
clock_t times(
struct tms *ptms
)
@@ -63,12 +66,21 @@ clock_t times(
return _times( ptms );
}
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
clock_t _times_r(
struct _reent *ptr,
struct tms *ptms
)
{
- return _times(ptms);
+ return _times( ptms );
}
#endif
diff --git a/c/src/exec/libcsupport/src/access.c b/c/src/exec/libcsupport/src/access.c
new file mode 100644
index 0000000000..a8be44a9a3
--- /dev/null
+++ b/c/src/exec/libcsupport/src/access.c
@@ -0,0 +1,46 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/c/src/exec/libcsupport/src/base_fs.c b/c/src/exec/libcsupport/src/base_fs.c
new file mode 100644
index 0000000000..c8c23e5b43
--- /dev/null
+++ b/c/src/exec/libcsupport/src/base_fs.c
@@ -0,0 +1,81 @@
+/*
+ * Base file system initialization
+ *
+ * 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/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_filesystem_location_info_t rtems_filesystem_current;
+rtems_filesystem_location_info_t rtems_filesystem_root;
+nlink_t rtems_filesystem_link_counts;
+
+/*
+ * Default mode for created files.
+ */
+
+mode_t rtems_filesystem_umask;
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system with one instantiation
+ * of the IMFS with a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *first_entry;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = S_IWOTH | S_IROTH;
+
+ init_fs_mount_table();
+
+ status = mount(
+ &first_entry,
+ &IMFS_ops,
+ "RW",
+ NULL,
+ NULL );
+ if( status == -1 ){
+ rtems_fatal_error_occurred( 0xABCD0002 );
+ }
+
+ rtems_filesystem_link_counts = 0;
+
+ rtems_filesystem_root = first_entry->mt_fs_root;
+
+ rtems_filesystem_current = rtems_filesystem_root;
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+}
diff --git a/c/src/exec/libcsupport/src/cfgetispeed.c b/c/src/exec/libcsupport/src/cfgetispeed.c
new file mode 100644
index 0000000000..61d97cb2f1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfgetispeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfgetospeed.c b/c/src/exec/libcsupport/src/cfgetospeed.c
new file mode 100644
index 0000000000..8815d436e9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfgetospeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfsetispeed.c b/c/src/exec/libcsupport/src/cfsetispeed.c
new file mode 100644
index 0000000000..37d3cd0584
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfsetispeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/cfsetospeed.c b/c/src/exec/libcsupport/src/cfsetospeed.c
new file mode 100644
index 0000000000..f01237103b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/cfsetospeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/chdir.c b/c/src/exec/libcsupport/src/chdir.c
new file mode 100644
index 0000000000..4acbc8cfe0
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chdir.c
@@ -0,0 +1,50 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/c/src/exec/libcsupport/src/chmod.c b/c/src/exec/libcsupport/src/chmod.c
new file mode 100644
index 0000000000..fa57d50691
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chmod.c
@@ -0,0 +1,40 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * 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/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "libio_.h"
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.handlers->fchmod)( &loc, mode );
+}
diff --git a/c/src/exec/libcsupport/src/chown.c b/c/src/exec/libcsupport/src/chown.c
new file mode 100644
index 0000000000..189096dcd1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/chown.c
@@ -0,0 +1,38 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * 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 <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "libio_.h"
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->chown )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->chown)( &temp_loc, owner, group );
+}
diff --git a/c/src/exec/libcsupport/src/close.c b/c/src/exec/libcsupport/src/close.c
new file mode 100644
index 0000000000..94ddb45c90
--- /dev/null
+++ b/c/src/exec/libcsupport/src/close.c
@@ -0,0 +1,70 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * 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 "libio_.h"
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+ int status;
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ int (*fp)(int fd);
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+ status = (*fp)( fd );
+ return status;
+ }
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+
+ if ( !iop->handlers )
+ set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->close )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->close)( iop );
+
+ rtems_libio_free( iop );
+
+ if (rc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( rc );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/closedir.c b/c/src/exec/libcsupport/src/closedir.c
index 5edb3499e6..4d948ec95b 100644
--- a/c/src/exec/libcsupport/src/closedir.c
+++ b/c/src/exec/libcsupport/src/closedir.c
@@ -1,9 +1,44 @@
/*
* closedir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <dirent.h>
@@ -11,10 +46,25 @@
#include <unistd.h>
#include <errno.h>
-int closedir(
- register DIR *dirp
-)
+
+#include "libio_.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
{
- errno = ENOSYS;
- return -1;
+ int fd;
+
+ if ( !dirp )
+ set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
}
diff --git a/c/src/exec/libcsupport/src/dup.c b/c/src/exec/libcsupport/src/dup.c
new file mode 100644
index 0000000000..c17db588a7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/dup.c
@@ -0,0 +1,23 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/c/src/exec/libcsupport/src/dup2.c b/c/src/exec/libcsupport/src/dup2.c
new file mode 100644
index 0000000000..5653425708
--- /dev/null
+++ b/c/src/exec/libcsupport/src/dup2.c
@@ -0,0 +1,49 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+
+#include "libio_.h"
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/c/src/exec/libcsupport/src/eval.c b/c/src/exec/libcsupport/src/eval.c
new file mode 100644
index 0000000000..bf7dd1c126
--- /dev/null
+++ b/c/src/exec/libcsupport/src/eval.c
@@ -0,0 +1,74 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * 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 "libio_.h"
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( follow_link ) {
+
+ if ( !pathloc->ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ type = (*pathloc->ops->node_type)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->eval_link)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
diff --git a/c/src/exec/libcsupport/src/fchmod.c b/c/src/exec/libcsupport/src/fchmod.c
new file mode 100644
index 0000000000..a3ca4507ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * 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 <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "libio_.h"
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fchmod().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode );
+}
+
diff --git a/c/src/exec/libcsupport/src/fcntl.c b/c/src/exec/libcsupport/src/fcntl.c
new file mode 100644
index 0000000000..f6f33534ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fcntl.c
@@ -0,0 +1,111 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include "libio_.h"
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ va_list ap;
+ rtems_libio_t *iop;
+
+ va_start( ap, cmd );
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fcntl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ /*
+ * This is how it appears that this case should work:
+ *
+ * filedes2 = va_arg( ap, int )
+ * if filedes2 is 0
+ * duplicate fd into a new descriptor
+ * else
+ * duplicate fd into specified descriptor after error checking it
+ *
+ * See dup2() in case we can eliminate stuff in there.
+ */
+ return -1;
+
+ case F_GETFD: /* get f_flags */
+ if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
+ return 1;
+ return 0;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ return 0;
+
+ case F_GETFL: /* more flags (cloexec) */
+ return -1;
+
+ case F_SETFL:
+ return -1;
+
+ case F_GETLK:
+ return -1;
+
+ case F_SETLK:
+ return -1;
+
+ case F_SETLKW:
+ return -1;
+
+ case F_SETOWN: /* for sockets. */
+ return -1;
+
+ case F_GETOWN: /* for sockets. */
+ return -1;
+
+ default:
+ break;
+ }
+ return -1;
+}
diff --git a/c/src/exec/libcsupport/src/fdatasync.c b/c/src/exec/libcsupport/src/fdatasync.c
new file mode 100644
index 0000000000..58a4c4e118
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fdatasync.c
@@ -0,0 +1,45 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * 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 <unistd.h>
+
+#include "libio_.h"
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fdatasync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync)( iop );
+}
diff --git a/c/src/exec/libcsupport/src/fpathconf.c b/c/src/exec/libcsupport/src/fpathconf.c
new file mode 100644
index 0000000000..ea2377e15b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fpathconf.c
@@ -0,0 +1,91 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * 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 "libio_.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then it is an error since fpathconf() is not included in the
+ * set.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the information request.
+ */
+
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/c/src/exec/libcsupport/src/fstat.c b/c/src/exec/libcsupport/src/fstat.c
new file mode 100644
index 0000000000..82d144dd2c
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fstat.c
@@ -0,0 +1,94 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * 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 <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "libio_.h"
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if (rtems_file_descriptor_type(fd)) {
+ switch (rtems_file_descriptor_type (fd)) {
+ case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
+ break;
+
+ case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
+#if !defined(__GO32__)
+ sbuf->st_mode = S_IFSOCK;
+ break;
+#endif
+
+ default:
+ set_errno_and_return_minus_one( EBADF );
+ }
+ }
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fstat)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/fsync.c b/c/src/exec/libcsupport/src/fsync.c
new file mode 100644
index 0000000000..a5ed1e99e7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * 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 <unistd.h>
+
+#include "libio_.h"
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fsync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fsync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync)( iop );
+}
diff --git a/c/src/exec/libcsupport/src/ftruncate.c b/c/src/exec/libcsupport/src/ftruncate.c
new file mode 100644
index 0000000000..7fb2286531
--- /dev/null
+++ b/c/src/exec/libcsupport/src/ftruncate.c
@@ -0,0 +1,60 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate)( iop, length );
+}
+
diff --git a/c/src/exec/libcsupport/src/getdents.c b/c/src/exec/libcsupport/src/getdents.c
index 9b16d82409..91631843b7 100644
--- a/c/src/exec/libcsupport/src/getdents.c
+++ b/c/src/exec/libcsupport/src/getdents.c
@@ -1,14 +1,59 @@
/*
- * Just enough to make newlib return an error.
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+
int getdents(
- int fd,
- void *buf,
- int len
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
)
{
- return -1;
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read)( iop, dd_buf, dd_len );
}
diff --git a/c/src/exec/libcsupport/src/hosterr.c b/c/src/exec/libcsupport/src/hosterr.c
index a55e4a7e84..6c0308df3b 100644
--- a/c/src/exec/libcsupport/src/hosterr.c
+++ b/c/src/exec/libcsupport/src/hosterr.c
@@ -13,31 +13,36 @@
*/
#include <rtems.h>
+#if defined(RTEMS_UNIX)
#include <errno.h>
-int host_errno(void);
+int host_errno( void );
/*
- * copy host errno, if any to thread aware errno, if any
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
*/
-void fix_syscall_errno(void)
+void fix_syscall_errno( void )
{
- errno = host_errno();
+ errno = host_errno();
}
/*
- * Get the host system errno, if any
- * When using newlib (or possibly other libc's) on top of UNIX
- * the errno returned by system calls may be unavailable due
- * to trickery of making errno thread aware.
- * This provides a kludge of getting at it.
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
*/
#undef errno
extern int errno;
int host_errno(void)
{
- return errno;
+ return errno;
}
-
+#endif
diff --git a/c/src/exec/libcsupport/src/ioctl.c b/c/src/exec/libcsupport/src/ioctl.c
new file mode 100644
index 0000000000..0aaf0379ae
--- /dev/null
+++ b/c/src/exec/libcsupport/src/ioctl.c
@@ -0,0 +1,57 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * 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 "libio_.h"
+
+int ioctl(
+ int fd,
+ unsigned32 command,
+ void * buffer
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_ioctl_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, command, buffer );
+ }
+
+ /*
+ * Now process the ioctl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->ioctl )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/c/src/exec/libcsupport/src/libio.c b/c/src/exec/libcsupport/src/libio.c
index 12682c1190..e63a4626d4 100644
--- a/c/src/exec/libcsupport/src/libio.c
+++ b/c/src/exec/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;
}
diff --git a/c/src/exec/libcsupport/src/link.c b/c/src/exec/libcsupport/src/link.c
new file mode 100644
index 0000000000..1cee54d0bf
--- /dev/null
+++ b/c/src/exec/libcsupport/src/link.c
@@ -0,0 +1,60 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * 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/libio.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+ result = (*parent_loc.ops->evalformake)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 )
+ set_errno_and_return_minus_one( result );
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry )
+ set_errno_and_return_minus_one( EXDEV );
+
+ if ( !parent_loc.ops->link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start );
+}
diff --git a/c/src/exec/libcsupport/src/lseek.c b/c/src/exec/libcsupport/src/lseek.c
new file mode 100644
index 0000000000..514f8cd912
--- /dev/null
+++ b/c/src/exec/libcsupport/src/lseek.c
@@ -0,0 +1,93 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * 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 <stdio.h>
+
+#include "libio_.h"
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_lseek_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, offset, whence );
+ }
+
+ /*
+ * Now process the lseek().
+ */
+
+ 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;
+ }
+
+ if ( !iop->handlers->lseek )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->lseek)( iop, offset, whence );
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
+
diff --git a/c/src/exec/libcsupport/src/malloc.c b/c/src/exec/libcsupport/src/malloc.c
index fac38585a7..f164e45f6c 100644
--- a/c/src/exec/libcsupport/src/malloc.c
+++ b/c/src/exec/libcsupport/src/malloc.c
@@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize(
#ifdef MALLOC_STATS
/* zero all the stats */
- (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats));
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
#endif
MSBUMP(space_available, length);
@@ -220,9 +220,11 @@ void *malloc(
{
unsigned32 actual_size;
unsigned32 current_depth;
- status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size);
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
MSBUMP(lifetime_allocated, actual_size);
- current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
if (current_depth > rtems_malloc_stats.max_depth)
rtems_malloc_stats.max_depth = current_depth;
}
@@ -335,10 +337,12 @@ void free(
void malloc_dump(void)
{
- unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
printf("Malloc stats\n");
- printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
(unsigned int) rtems_malloc_stats.space_available / 1024,
(unsigned int) allocated / 1024,
/* avoid float! */
diff --git a/c/src/exec/libcsupport/src/mkdir.c b/c/src/exec/libcsupport/src/mkdir.c
new file mode 100644
index 0000000000..18fc7171c7
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
+
diff --git a/c/src/exec/libcsupport/src/mkfifo.c b/c/src/exec/libcsupport/src/mkfifo.c
new file mode 100644
index 0000000000..6b3ece5650
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mkfifo.c
@@ -0,0 +1,25 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/c/src/exec/libcsupport/src/mknod.c b/c/src/exec/libcsupport/src/mknod.c
new file mode 100644
index 0000000000..4f83321ecd
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mknod.c
@@ -0,0 +1,60 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc );
+}
diff --git a/c/src/exec/libcsupport/src/mount.c b/c/src/exec/libcsupport/src/mount.c
new file mode 100644
index 0000000000..fa8cebc3f9
--- /dev/null
+++ b/c/src/exec/libcsupport/src/mount.c
@@ -0,0 +1,299 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+/*
+ * XXX
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+);
+
+int init_fs_mount_table( void );
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_options_t options;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Are the file system options valid?
+ */
+
+ options = get_file_system_options( fsoptions );
+ if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Is the file system type valid?
+ */
+
+ if ( fs_ops == NULL ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) );
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if( device )
+ sprintf( temp_mt_entry->dev, "%s", device );
+ else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+ if ( rtems_filesystem_evaluate_path(
+ mount_point,
+ RTEMS_LIBIO_PERMS_RWX,
+ &temp_loc ,
+ TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry
+ */
+
+ temp_mt_entry->mt_point_node.node_access = temp_loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = temp_loc.handlers;
+ temp_mt_entry->mt_point_node.ops = temp_loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !temp_loc.ops->mount ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( temp_loc.ops->mount( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ }
+ else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( !fs_ops->fsmount_me ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( fs_ops->fsmount_me( temp_mt_entry ) )
+ goto cleanup_and_bail;
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * get_file_system_options
+ *
+ * This routine will determine is the text string that represents the options
+ * that are to be used to mount the file system are actually valid. If the
+ * options are valid the appropriate file system options type will be returned
+ * to the calling routine.
+ */
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+)
+{
+ if ( strcmp( "RO", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_ONLY;
+ if ( strcmp( "RW", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_WRITE_ONLY;
+ else
+ return RTEMS_FILESYSTEM_BAD_OPTIONS;
+}
+
+
+
+/*
+ * search_mt_for_mount_point
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_point_node to the node describing the selected
+ * mount point.. If any of the mount table file system mount point nodes
+ * match the new file system selected mount point node, we are attempting
+ * to mount the new file system onto a node that already has a file system
+ * mounted to it. This is not a permitted operation.
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_point_node.node_access ==
+ location_of_mount_point->node_access )
+ return FOUND;
+ }
+ return NOT_FOUND;
+}
+
diff --git a/c/src/exec/libcsupport/src/newlibc.c b/c/src/exec/libcsupport/src/newlibc.c
index a6acc1c8d7..bea592a46e 100644
--- a/c/src/exec/libcsupport/src/newlibc.c
+++ b/c/src/exec/libcsupport/src/newlibc.c
@@ -1,21 +1,14 @@
-
/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
* COPYRIGHT (c) 1994 by Division Incorporated
*
* 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.
*
- * Description:
- * Implementation of hooks for the CYGNUS newlib libc
- * These hooks set things up so that:
- * '_REENT' is switched at task switch time.
- *
- *
- * TODO:
- *
- * NOTE:
- *
* $Id$
*
*/
@@ -47,7 +40,21 @@
#include <stdio.h>
#endif
-#include "internal.h"
+/*
+ * Private routines
+ */
+
+void MY_task_set_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad,
+ rtems_unsigned32 note
+);
+
+rtems_unsigned32 MY_task_get_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad
+);
+
#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
@@ -304,7 +311,7 @@ libc_init(int reentrant)
rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
&libc_extension, &extension_id);
if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_fatal_error_occurred( rc );
libc_reentrant = reentrant;
}
@@ -353,11 +360,14 @@ int get_errno()
/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
#if !defined(RTEMS_UNIX) && !defined(_AM29K)
+#if !defined(pc386)
void _exit(int status)
{
libc_wrapup(); /* Why? XXX */
rtems_shutdown_executive(status);
}
+#endif
+
#else
void exit(int status)
@@ -426,4 +436,46 @@ unsigned int sleep(
#endif
+/*
+ * Newlib Interface Support
+ *
+ * Routines to Access Internal RTEMS Resources without violating
+ * kernel visibility.
+ *
+ */
+
+void MY_task_set_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad,
+ unsigned32 note
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( api )
+ api->Notepads[ notepad ] = note;
+}
+
+
+unsigned32 MY_task_get_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ return api->Notepads[ notepad ];
+}
+
+void *MY_CPU_Context_FP_start(
+ void *base,
+ unsigned32 offset
+)
+{
+ return _CPU_Context_Fp_start( base, offset );
+}
#endif
diff --git a/c/src/exec/libcsupport/src/no_libc.c b/c/src/exec/libcsupport/src/no_libc.c
index 5a58ba761c..4bd02c4b27 100644
--- a/c/src/exec/libcsupport/src/no_libc.c
+++ b/c/src/exec/libcsupport/src/no_libc.c
@@ -1,6 +1,4 @@
-
-/* no_libc.h
- *
+/*
* This file contains stubs for the reentrancy hooks when
* an unknown C library is used.
*
@@ -17,15 +15,15 @@
#include <rtems.h>
-#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
#include "libcsupport.h"
-#include "internal.h"
#include <stdlib.h> /* for free() */
-void
-libc_init(int reentrant)
+void libc_init(
+ int reentrant
+)
{
}
@@ -34,11 +32,15 @@ void libc_suspend_main(void)
}
-void libc_global_exit(rtems_unsigned32 code)
+void libc_global_exit(
+ rtems_unsigned32 code
+)
{
}
-void _exit(int status)
+void _exit(
+ int status
+)
{
}
diff --git a/c/src/exec/libcsupport/src/open.c b/c/src/exec/libcsupport/src/open.c
new file mode 100644
index 0000000000..4cdf5acf35
--- /dev/null
+++ b/c/src/exec/libcsupport/src/open.c
@@ -0,0 +1,202 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * 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 "libio_.h"
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and eitehr the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * 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().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+
+ status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ goto done;
+ }
+
+ /*
+ * Fill in the file control block based on the temp_loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = temp_loc.handlers;
+ iop->file_info = temp_loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = temp_loc;
+
+ if ( !iop->handlers->open ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ set_errno_and_return_minus_one( rc );
+ }
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/opendir.c b/c/src/exec/libcsupport/src/opendir.c
index e303eb28e5..f0e9488684 100644
--- a/c/src/exec/libcsupport/src/opendir.c
+++ b/c/src/exec/libcsupport/src/opendir.c
@@ -1,17 +1,85 @@
/*
* opendir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
-DIR *opendir(
- const char *name
-)
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
{
- return NULL;
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
}
diff --git a/c/src/exec/libcsupport/src/pathconf.c b/c/src/exec/libcsupport/src/pathconf.c
new file mode 100644
index 0000000000..e19d1329f4
--- /dev/null
+++ b/c/src/exec/libcsupport/src/pathconf.c
@@ -0,0 +1,38 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/c/src/lib/libc/_execve.c b/c/src/exec/libcsupport/src/pipe.c
index d1ad365b57..35dcf627bb 100644
--- a/c/src/lib/libc/_execve.c
+++ b/c/src/exec/libcsupport/src/pipe.c
@@ -1,9 +1,5 @@
-#include <rtems.h>
-
-#if defined(RTEMS_NEWLIB)
/*
- * RTEMS Dummy _execveImplementation
- *
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -16,16 +12,12 @@
* $Id$
*/
-#include <unistd.h>
#include <errno.h>
-int _execve(
- const char *path,
- char *const argv[],
- char *const environ[]
+int pipe(
+ int filsdes[2]
)
{
errno = ENOSYS;
return -1;
}
-#endif
diff --git a/c/src/exec/libcsupport/src/read.c b/c/src/exec/libcsupport/src/read.c
new file mode 100644
index 0000000000..150fe675ab
--- /dev/null
+++ b/c/src/exec/libcsupport/src/read.c
@@ -0,0 +1,84 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * 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 "libio_.h"
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int read(
+ int fd,
+ void *buffer,
+ unsigned32 count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_read_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the read().
+ */
+
+ 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 );
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/readdir.c b/c/src/exec/libcsupport/src/readdir.c
index d592a62b99..f950d56171 100644
--- a/c/src/exec/libcsupport/src/readdir.c
+++ b/c/src/exec/libcsupport/src/readdir.c
@@ -1,14 +1,77 @@
/*
* readdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
-struct dirent *readdir(
- register DIR *dirp
-)
-{
- return NULL;
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
}
diff --git a/c/src/exec/libcsupport/src/readlink.c b/c/src/exec/libcsupport/src/readlink.c
new file mode 100644
index 0000000000..22de51e88f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/readlink.c
@@ -0,0 +1,43 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * 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 "libio_.h"
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if (!buf)
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( !loc.ops->readlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->readlink)( &loc, buf, bufsize );
+}
diff --git a/c/src/exec/libcsupport/src/rewinddir.c b/c/src/exec/libcsupport/src/rewinddir.c
index c85e6fd4d0..04313a6042 100644
--- a/c/src/exec/libcsupport/src/rewinddir.c
+++ b/c/src/exec/libcsupport/src/rewinddir.c
@@ -1,7 +1,14 @@
/*
* rewinddir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/types.h>
@@ -15,6 +22,14 @@ void rewinddir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
+
}
diff --git a/c/src/exec/libcsupport/src/rmdir.c b/c/src/exec/libcsupport/src/rmdir.c
new file mode 100644
index 0000000000..6c0331087f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/rmdir.c
@@ -0,0 +1,56 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libio_.h"
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.ops->rmnod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->rmnod)( &loc );
+}
diff --git a/c/src/exec/libcsupport/src/scandir.c b/c/src/exec/libcsupport/src/scandir.c
index 380415dd97..9ba1cb7bec 100644
--- a/c/src/exec/libcsupport/src/scandir.c
+++ b/c/src/exec/libcsupport/src/scandir.c
@@ -1,7 +1,50 @@
/*
* scandir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
@@ -9,15 +52,98 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-int scandir(
- const char *dirname,
- struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*dcomp)(const void *, const void *)
-)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d, *p, **names;
+ register size_t nitems;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1);
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1); /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
{
- errno = ENOSYS;
- return -1;
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
}
diff --git a/c/src/exec/libcsupport/src/seekdir.c b/c/src/exec/libcsupport/src/seekdir.c
index e591adbb9f..80802b56c6 100644
--- a/c/src/exec/libcsupport/src/seekdir.c
+++ b/c/src/exec/libcsupport/src/seekdir.c
@@ -1,7 +1,14 @@
/*
* seekdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/param.h>
@@ -12,10 +19,20 @@
#include <errno.h>
void seekdir(
- DIR *dirp,
- long loc
+ DIR *dirp,
+ long loc
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
}
diff --git a/c/src/exec/libcsupport/src/stat.c b/c/src/exec/libcsupport/src/stat.c
new file mode 100644
index 0000000000..8ad7e61511
--- /dev/null
+++ b/c/src/exec/libcsupport/src/stat.c
@@ -0,0 +1,79 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * 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>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int stat(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ return (*loc.handlers->fstat)( &loc, buf );
+}
+#endif
+
+/*
+ * _stat_r
+ *
+ * This is the Newlib dependent reentrant version of stat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _stat_r(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return stat( path, buf );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/symlink.c b/c/src/exec/libcsupport/src/symlink.c
new file mode 100644
index 0000000000..ca9673f51b
--- /dev/null
+++ b/c/src/exec/libcsupport/src/symlink.c
@@ -0,0 +1,34 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * 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 "libio_.h"
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ return (*loc.ops->symlink)( &loc, actualpath, name_start);
+}
+
diff --git a/c/src/exec/libcsupport/src/tcdrain.c b/c/src/exec/libcsupport/src/tcdrain.c
index 585871cc90..c2749a90e1 100644
--- a/c/src/exec/libcsupport/src/tcdrain.c
+++ b/c/src/exec/libcsupport/src/tcdrain.c
@@ -1,9 +1,15 @@
/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcdrain.
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
*
- * $Id$
+ * 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>
@@ -13,14 +19,15 @@
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>
+#include <sys/ioctl.h>
-#include "internal.h"
#include "libio.h"
-int
-tcdrain(int fd)
+int tcdrain(
+ int fd
+)
{
- return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0);
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
}
#endif
diff --git a/c/src/exec/libcsupport/src/tcgetattr.c b/c/src/exec/libcsupport/src/tcgetattr.c
new file mode 100644
index 0000000000..2d3e4d7e3c
--- /dev/null
+++ b/c/src/exec/libcsupport/src/tcgetattr.c
@@ -0,0 +1,33 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/tcsetattr.c b/c/src/exec/libcsupport/src/tcsetattr.c
new file mode 100644
index 0000000000..c0ed509a0f
--- /dev/null
+++ b/c/src/exec/libcsupport/src/tcsetattr.c
@@ -0,0 +1,38 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+#include "libio_.h"
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ if ( opt != TCSANOW )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/exec/libcsupport/src/telldir.c b/c/src/exec/libcsupport/src/telldir.c
index eee8d925ec..cea6cc08cb 100644
--- a/c/src/exec/libcsupport/src/telldir.c
+++ b/c/src/exec/libcsupport/src/telldir.c
@@ -1,7 +1,14 @@
/*
* telldir() - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/param.h>
@@ -9,15 +16,24 @@
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
-#include <rtems.h>
-#include "libio.h"
+#include "libio_.h"
+
long telldir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ rtems_libio_t *iop;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
}
diff --git a/c/src/exec/libcsupport/src/truncate.c b/c/src/exec/libcsupport/src/truncate.c
new file mode 100644
index 0000000000..145e596654
--- /dev/null
+++ b/c/src/exec/libcsupport/src/truncate.c
@@ -0,0 +1,41 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
+
diff --git a/c/src/exec/libcsupport/src/umask.c b/c/src/exec/libcsupport/src/umask.c
new file mode 100644
index 0000000000..35229a30a1
--- /dev/null
+++ b/c/src/exec/libcsupport/src/umask.c
@@ -0,0 +1,30 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include "libio_.h"
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/c/src/exec/libcsupport/src/unixlibc.c b/c/src/exec/libcsupport/src/unixlibc.c
index 3e757e313d..a581d95534 100644
--- a/c/src/exec/libcsupport/src/unixlibc.c
+++ b/c/src/exec/libcsupport/src/unixlibc.c
@@ -1,5 +1,15 @@
/*
* $Id$
+ * UNIX Port C Library Support
+ *
+ * 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.
+ *
*/
#include <rtems.h>
diff --git a/c/src/exec/libcsupport/src/unlink.c b/c/src/exec/libcsupport/src/unlink.c
new file mode 100644
index 0000000000..d4a5520bcb
--- /dev/null
+++ b/c/src/exec/libcsupport/src/unlink.c
@@ -0,0 +1,44 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ if ( !loc.ops->unlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->unlink)( &loc );
+}
diff --git a/c/src/exec/libcsupport/src/unmount.c b/c/src/exec/libcsupport/src/unmount.c
new file mode 100644
index 0000000000..f50e63ff42
--- /dev/null
+++ b/c/src/exec/libcsupport/src/unmount.c
@@ -0,0 +1,214 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+);
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a mount_path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *mount_path
+)
+{
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_mount_table_entry_t temp_mt_entry;
+ int result;
+
+ /*
+ * Are there any file systems below the mount_path specified
+ */
+
+ status = file_systems_below_this_mountpoint(
+ mount_path,
+ &temp_loc,
+ &temp_mt_entry
+ );
+
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Is the current node reference pointing to a node in the file system
+ * we are attempting to unmount ?
+ */
+
+ if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being mounted on to do its cleanup.
+ * XXX - Did I change these correctly ??? It looks like either I did
+ * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped.
+ * XXX Add to the mt_point_node unmount to set the mt_entry back to null
+ * XXX I will step off in space when evaluating past the end of the node.
+ */
+
+ if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Run the unmount function for the subordinate file system.
+ */
+
+ if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the file system to clean up.
+ */
+
+ result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry );
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry );
+
+ /*
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ free( temp_loc.mt_entry );
+
+ return result;
+
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+ rtems_filesystem_mount_table_entry_t *current_fs_mt_entry;
+
+ /*
+ * Is the mount_path even a valid node name in the existing tree?
+ */
+
+ if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) )
+ return -1;
+
+ /*
+ * Look for the node defined in temp_loc as a mount point in the
+ * mount table chain.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.node_access ==
+ temp_loc->node_access ) {
+ current_fs_mt_entry = the_mount_entry;
+ *temp_loc = current_fs_mt_entry->mt_fs_root;
+ goto after_real_mount_point_found;
+ }
+ }
+ set_errno_and_return_minus_one( EACCES );
+
+
+after_real_mount_point_found:
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+
+ /*
+ * Exclude the current file systems mount table entry from the test
+ */
+
+ if ( current_fs_mt_entry != the_mount_entry ) {
+ if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) {
+
+ /*
+ * There is at least one fs below the fs on the mount_path.
+ */
+ set_errno_and_return_minus_one( EBUSY );
+ }
+ }
+ }
+
+ *temp_mt_entry = *current_fs_mt_entry;
+
+ return 0;
+}
diff --git a/c/src/exec/libcsupport/src/utime.c b/c/src/exec/libcsupport/src/utime.c
new file mode 100644
index 0000000000..f1a12ee1b2
--- /dev/null
+++ b/c/src/exec/libcsupport/src/utime.c
@@ -0,0 +1,35 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * 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 <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime );
+}
diff --git a/c/src/exec/libcsupport/src/write.c b/c/src/exec/libcsupport/src/write.c
new file mode 100644
index 0000000000..7e0953bb90
--- /dev/null
+++ b/c/src/exec/libcsupport/src/write.c
@@ -0,0 +1,92 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * 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 "libio_.h"
+
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int write( /* XXX this should return a ssize_t */
+ int fd,
+ const void *buffer,
+ unsigned32 count /* XXX this should be a size_t */
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_write_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the write() request.
+ */
+
+ 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 );
+
+ if ( !iop->handlers->write )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+long _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/exec/libfs/src/imfs/deviceio.c b/c/src/exec/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * 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/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/exec/libfs/src/imfs/imfs.h b/c/src/exec/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * 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$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/exec/libfs/src/imfs/imfs_chown.c b/c/src/exec/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_creat.c b/c/src/exec/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * 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 <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_debug.c b/c/src/exec/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * 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 <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_directory.c b/c/src/exec/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_eval.c b/c/src/exec/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_fchmod.c b/c/src/exec/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_free.c b/c/src/exec/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_getchild.c b/c/src/exec/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * 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 <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_gtkn.c b/c/src/exec/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * 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 <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_init.c b/c/src/exec/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_initsupp.c b/c/src/exec/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_link.c b/c/src/exec/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_mknod.c b/c/src/exec/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_mount.c b/c/src/exec/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_ntype.c b/c/src/exec/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_readlink.c b/c/src/exec/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_rmnod.c b/c/src/exec/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_stat.c b/c/src/exec/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_symlink.c b/c/src/exec/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/exec/libfs/src/imfs/imfs_unlink.c b/c/src/exec/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_unmount.c b/c/src/exec/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/imfs_utime.c b/c/src/exec/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/exec/libfs/src/imfs/ioman.c b/c/src/exec/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/c/src/exec/libfs/src/imfs/memfile.c b/c/src/exec/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/exec/libfs/src/imfs/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/exec/posix/include/sys/Makefile.in b/c/src/exec/posix/include/sys/Makefile.in
index d7d9281094..e787a7a977 100644
--- a/c/src/exec/posix/include/sys/Makefile.in
+++ b/c/src/exec/posix/include/sys/Makefile.in
@@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
#H_PIECES=utsname
-H_PIECES=
+H_PIECES=utime ioctl
H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
SRCS=$(H_FILES)
diff --git a/c/src/exec/posix/src/getpid.c b/c/src/exec/posix/src/getpid.c
index b42981398a..8e912adf39 100644
--- a/c/src/exec/posix/src/getpid.c
+++ b/c/src/exec/posix/src/getpid.c
@@ -20,3 +20,22 @@ pid_t getpid( void )
{
return _Objects_Local_node;
}
+
+/*
+ * _getpid_r
+ *
+ * This is the Newlib dependent reentrant version of getpid().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+pid_t _getpid_r(
+ struct _reent *ptr
+)
+{
+ return getpid();
+}
+#endif
+
diff --git a/c/src/exec/posix/src/psignal.c b/c/src/exec/posix/src/psignal.c
index 5db634a924..1450164021 100644
--- a/c/src/exec/posix/src/psignal.c
+++ b/c/src/exec/posix/src/psignal.c
@@ -1222,6 +1222,26 @@ int kill(
}
/*
+ * _kill_r
+ *
+ * This is the Newlib dependent reentrant version of kill().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _kill_r(
+ struct _reent *ptr,
+ pid_t pid,
+ int sig
+)
+{
+ return kill( pid, sig );
+}
+#endif
+
+/*
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
*/
diff --git a/c/src/exec/posix/sys/Makefile.in b/c/src/exec/posix/sys/Makefile.in
index d7d9281094..e787a7a977 100644
--- a/c/src/exec/posix/sys/Makefile.in
+++ b/c/src/exec/posix/sys/Makefile.in
@@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
#H_PIECES=utsname
-H_PIECES=
+H_PIECES=utime ioctl
H_FILES=$(H_PIECES:%=$(srcdir)/%.h)
SRCS=$(H_FILES)
diff --git a/c/src/exec/sapi/src/io.c b/c/src/exec/sapi/src/io.c
index 92de490885..d6e669c4fc 100644
--- a/c/src/exec/sapi/src/io.c
+++ b/c/src/exec/sapi/src/io.c
@@ -92,6 +92,7 @@ void _IO_Initialize_all_drivers( void )
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_register_name(
char *device_name,
rtems_device_major_number major,
@@ -124,6 +125,7 @@ rtems_status_code rtems_io_register_name(
return RTEMS_TOO_MANY;
}
+#endif
/*PAGE
*
@@ -140,6 +142,7 @@ rtems_status_code rtems_io_register_name(
* error code - if unsuccessful
*/
+#if 0
rtems_status_code rtems_io_lookup_name(
const char *name,
rtems_driver_name_t **device_info
@@ -161,6 +164,7 @@ rtems_status_code rtems_io_lookup_name(
*device_info = 0;
return RTEMS_UNSATISFIED;
}
+#endif
/*PAGE
diff --git a/c/src/lib/include/rtems/libio.h b/c/src/lib/include/rtems/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/lib/include/rtems/libio.h
+++ b/c/src/lib/include/rtems/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * 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$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/lib/include/rtems/libio_.h b/c/src/lib/include/rtems/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/lib/include/rtems/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * 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$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.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 */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#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 rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/lib/libbsp/shared/bsplibc.c b/c/src/lib/libbsp/shared/bsplibc.c
index 164e33a016..faa5e436c7 100644
--- a/c/src/lib/libbsp/shared/bsplibc.c
+++ b/c/src/lib/libbsp/shared/bsplibc.c
@@ -22,7 +22,7 @@ void bsp_libc_init(
/*
* Init the RTEMS libio facility to provide UNIX-like system
- * calls for use by newlib (ie: provide __rtems_open, __rtems_close, etc)
+ * calls for use by newlib (ie: provide open, close, etc)
* Uses malloc() to get area for the iops, so must be after malloc init
*/
diff --git a/c/src/lib/libbsp/shared/bsppost.c b/c/src/lib/libbsp/shared/bsppost.c
index d3d14786ce..28a41bf4ea 100644
--- a/c/src/lib/libbsp/shared/bsppost.c
+++ b/c/src/lib/libbsp/shared/bsppost.c
@@ -22,13 +22,13 @@ bsp_postdriver_hook(void)
error_code = 'S' << 24 | 'T' << 16;
- if ((stdin_fd = __rtems_open("/dev/console", O_RDONLY, 0)) == -1)
+ if ((stdin_fd = open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
- if ((stdout_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1)
+ if ((stdout_fd = open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
- if ((stderr_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1)
+ if ((stderr_fd = open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
diff --git a/c/src/lib/libc/CASES b/c/src/lib/libc/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/c/src/lib/libc/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/c/src/lib/libc/Makefile.in b/c/src/lib/libc/Makefile.in
index c9fbf72795..d3bc2afbc1 100644
--- a/c/src/lib/libc/Makefile.in
+++ b/c/src/lib/libc/Makefile.in
@@ -11,34 +11,59 @@ PROJECT_ROOT = @PROJECT_ROOT@
LIBNAME=libcsupport.a
LIB=${ARCH}/${LIBNAME}
-# define TARGET_PIECES later based on RTEMS_CPU definition
+BASE_FS_PIECES=base_fs mount unmount ioman \
+ libio eval
+
+IMFS_PIECES= imfs_chown imfs_creat imfs_directory imfs_eval imfs_free \
+ imfs_gtkn imfs_init imfs_link imfs_mknod imfs_mount imfs_fchmod \
+ imfs_rmnod imfs_unlink imfs_unmount imfs_utime imfs_ntype imfs_stat \
+ imfs_getchild memfile deviceio imfs_handlers imfs_debug imfs_symlink \
+ imfs_readlink
+
+TERMIOS_PIECES= cfgetispeed cfgetospeed cfsetispeed cfsetospeed \
+ tcgetattr tcsetattr tcdrain termios
+
+SYSTEM_CALL_PIECES=\
+ open close read write lseek ioctl \
+ mkdir mknod mkfifo rmdir chdir \
+ chmod fchmod chown \
+ link unlink umask ftruncate utime \
+ fstat fcntl fpathconf getdents \
+ fsync fdatasync pipe dup dup2 \
+ symlink readlink
+
+DIRECTORY_SCAN_PIECES=\
+ opendir closedir readdir rewinddir scandir seekdir telldir
+
+LIBC_GLUE_PIECES=\
+ malloc __brk __sbrk \
+ __gettod __times \
+ truncate access stat pathconf \
+ newlibc no_libc unixlibc hosterr
# C and C++ source names, if any, go here -- minus the .c or .cc
-C_PIECES=__times _execve malloc syscalls \
- no_libc support libio hosterr tcattr tcdrain \
- cfiospeed termios $(TARGET_PIECES)
+C_PIECES=\
+ $(LIBC_GLUE_PIECES) \
+ $(TERMIOS_PIECES) \
+ $(SYSTEM_CALL_PIECES) \
+ $(DIRECTORY_SCAN_PIECES) \
+ $(BASE_FS_PIECES) \
+ $(IMFS_PIECES)
+
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=$(srcdir)/libcsupport.h
SYS_H_FILES=
RTEMS_H_FILES=$(srcdir)/libio.h
-PRIVATE_H_FILES=$(srcdir)/internal.h
INSTALLED_H_FILES=$(srcdir)/libio.h $(srcdir)/libcsupport.h
-SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES) $(PRIVATE_H_FILES)
+SRCS=$(C_FILES) $(H_FILES) $(SYS_H_FILES) $(RTEMS_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/lib.cfg
-ifeq ($(RTEMS_CPU),unix)
-TARGET_PIECES=unixlibc
-else
-TARGET_PIECES=__brk __gettod newlibc newlibif newlibifr \
- getdents readdir opendir closedir rewinddir scandir seekdir telldir
-endif
-
#
# Add local stuff here using +=
#
diff --git a/c/src/lib/libc/TODO b/c/src/lib/libc/TODO
new file mode 100644
index 0000000000..9d894688d9
--- /dev/null
+++ b/c/src/lib/libc/TODO
@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
diff --git a/c/src/lib/libc/__brk.c b/c/src/lib/libc/__brk.c
index 4dab22c729..24efa93adb 100644
--- a/c/src/lib/libc/__brk.c
+++ b/c/src/lib/libc/__brk.c
@@ -1,10 +1,7 @@
-#if !defined(RTEMS_UNIX)
-
/*
- * RTEMS "Broken" __brk/__sbrk Implementation
- *
- * NOTE: sbrk is BSP provided.
+ * RTEMS "Broken" __brk Implementation
*
+ * NOTE: sbrk() is provided by each BSP.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,27 +15,15 @@
*/
#include <rtems.h>
+#if !defined(RTEMS_UNIX)
-#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#ifdef RTEMS_NEWLIB
-#include <reent.h>
-#endif
-#include <unistd.h>
-
-/* we use RTEMS for memory management. We don't need sbrk */
-void * __sbrk(int incr)
-{
- errno = EINVAL;
- return (void *)0;
-}
-
-int __brk( const void *endds )
+int __brk(
+ const void *endds
+)
{
errno = EINVAL;
return -1;
}
-
#endif
diff --git a/c/src/lib/libc/__gettod.c b/c/src/lib/libc/__gettod.c
index dc83c47ce4..16857da870 100644
--- a/c/src/lib/libc/__gettod.c
+++ b/c/src/lib/libc/__gettod.c
@@ -1,11 +1,5 @@
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-
-#include <rtems.h>
-
-#if !defined(RTEMS_UNIX)
/*
- * RTEMS gettimeofday Implementation
- *
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -18,6 +12,11 @@
* $Id$
*/
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
#ifdef RTEMS_NEWLIB
#include <sys/reent.h>
#endif
@@ -61,7 +60,7 @@ int gettimeofday(
*
* NOTE: XXX this routine should really be in the executive proper.
*/
-
+
rtems_interrupt_disable(level);
seconds = _TOD_Seconds_since_epoch;
microseconds = _TOD_Current.ticks;
@@ -86,7 +85,7 @@ int gettimeofday(
return 0;
}
-#if defined(RTEMS_NEWLIB)
+#if defined(RTEMS_NEWLIB)
/*
* "Reentrant" version
@@ -102,7 +101,7 @@ int _gettimeofday_r(
}
/*
- * "System call" version
+ * "System call" version
*/
int _gettimeofday(
diff --git a/c/src/lib/libc/__sbrk.c b/c/src/lib/libc/__sbrk.c
new file mode 100644
index 0000000000..b1d31467fd
--- /dev/null
+++ b/c/src/lib/libc/__sbrk.c
@@ -0,0 +1,29 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * 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>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/c/src/lib/libc/__times.c b/c/src/lib/libc/__times.c
index 635bf8e062..5f7525ec5f 100644
--- a/c/src/lib/libc/__times.c
+++ b/c/src/lib/libc/__times.c
@@ -1,6 +1,5 @@
/*
- * RTEMS _times Implementation
- *
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
@@ -25,8 +24,8 @@ clock_t _times(
struct tms *ptms
)
{
- rtems_status_code status;
- rtems_interval ticks_since_boot;
+ rtems_status_code status;
+ rtems_interval ticks;
if ( !ptms ) {
errno = EFAULT;
@@ -34,21 +33,19 @@ clock_t _times(
}
/* "POSIX" does not seem to allow for not having a TOD */
- status = rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &ticks_since_boot
- );
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
if ( status != RTEMS_SUCCESSFUL ) {
assert( 0 );
return -1;
}
/*
- * RTEMS has no notion of system versus user time and does
- * not (as of 3.2.0) keep track of CPU usage on a per task basis.
+ * RTEMS has no notion of system versus user time and although
+ * a way to keep track of per task CPU usage was added since
+ * 3.6.0, this routine does not utilize it yet.
*/
- ptms->tms_utime = ticks_since_boot;
+ ptms->tms_utime = ticks;
ptms->tms_stime = 0;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
@@ -56,6 +53,12 @@ clock_t _times(
return 0;
}
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
clock_t times(
struct tms *ptms
)
@@ -63,12 +66,21 @@ clock_t times(
return _times( ptms );
}
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
clock_t _times_r(
struct _reent *ptr,
struct tms *ptms
)
{
- return _times(ptms);
+ return _times( ptms );
}
#endif
diff --git a/c/src/lib/libc/access.c b/c/src/lib/libc/access.c
new file mode 100644
index 0000000000..a8be44a9a3
--- /dev/null
+++ b/c/src/lib/libc/access.c
@@ -0,0 +1,46 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/base_fs.c b/c/src/lib/libc/base_fs.c
new file mode 100644
index 0000000000..c8c23e5b43
--- /dev/null
+++ b/c/src/lib/libc/base_fs.c
@@ -0,0 +1,81 @@
+/*
+ * Base file system initialization
+ *
+ * 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/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_filesystem_location_info_t rtems_filesystem_current;
+rtems_filesystem_location_info_t rtems_filesystem_root;
+nlink_t rtems_filesystem_link_counts;
+
+/*
+ * Default mode for created files.
+ */
+
+mode_t rtems_filesystem_umask;
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system with one instantiation
+ * of the IMFS with a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *first_entry;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = S_IWOTH | S_IROTH;
+
+ init_fs_mount_table();
+
+ status = mount(
+ &first_entry,
+ &IMFS_ops,
+ "RW",
+ NULL,
+ NULL );
+ if( status == -1 ){
+ rtems_fatal_error_occurred( 0xABCD0002 );
+ }
+
+ rtems_filesystem_link_counts = 0;
+
+ rtems_filesystem_root = first_entry->mt_fs_root;
+
+ rtems_filesystem_current = rtems_filesystem_root;
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ status = mkdir( "/dev", S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+}
diff --git a/c/src/lib/libc/cfgetispeed.c b/c/src/lib/libc/cfgetispeed.c
new file mode 100644
index 0000000000..61d97cb2f1
--- /dev/null
+++ b/c/src/lib/libc/cfgetispeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/c/src/lib/libc/cfgetospeed.c b/c/src/lib/libc/cfgetospeed.c
new file mode 100644
index 0000000000..8815d436e9
--- /dev/null
+++ b/c/src/lib/libc/cfgetospeed.c
@@ -0,0 +1,29 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/c/src/lib/libc/cfiospeed.c b/c/src/lib/libc/cfiospeed.c
deleted file mode 100644
index c2f40d3892..0000000000
--- a/c/src/lib/libc/cfiospeed.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines cfgetispeed, cfgetospeed, cfsetispeed and cfsetospeed.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-speed_t
-cfgetospeed(const struct termios *tp)
-{
- return tp->c_cflag & CBAUD;
-}
-
-int
-cfsetospeed(struct termios *tp, speed_t speed)
-{
- if (speed & ~CBAUD) {
- errno = EINVAL;
- return -1;
- }
- tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
- return 0;
-}
-
-speed_t
-cfgetispeed(const struct termios *tp)
-{
- return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
-}
-
-int
-cfsetispeed(struct termios *tp, speed_t speed)
-{
- if (speed & ~CBAUD) {
- errno = EINVAL;
- return -1;
- }
- tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
- return 0;
-}
-
-#endif
diff --git a/c/src/lib/libc/cfsetispeed.c b/c/src/lib/libc/cfsetispeed.c
new file mode 100644
index 0000000000..37d3cd0584
--- /dev/null
+++ b/c/src/lib/libc/cfsetispeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/c/src/lib/libc/cfsetospeed.c b/c/src/lib/libc/cfsetospeed.c
new file mode 100644
index 0000000000..f01237103b
--- /dev/null
+++ b/c/src/lib/libc/cfsetospeed.c
@@ -0,0 +1,36 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "libio_.h"
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/c/src/lib/libc/chdir.c b/c/src/lib/libc/chdir.c
new file mode 100644
index 0000000000..4acbc8cfe0
--- /dev/null
+++ b/c/src/lib/libc/chdir.c
@@ -0,0 +1,50 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/chmod.c b/c/src/lib/libc/chmod.c
new file mode 100644
index 0000000000..fa57d50691
--- /dev/null
+++ b/c/src/lib/libc/chmod.c
@@ -0,0 +1,40 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * 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/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "libio_.h"
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.handlers->fchmod)( &loc, mode );
+}
diff --git a/c/src/lib/libc/chown.c b/c/src/lib/libc/chown.c
new file mode 100644
index 0000000000..189096dcd1
--- /dev/null
+++ b/c/src/lib/libc/chown.c
@@ -0,0 +1,38 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * 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 <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include "libio_.h"
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->chown )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->chown)( &temp_loc, owner, group );
+}
diff --git a/c/src/lib/libc/close.c b/c/src/lib/libc/close.c
new file mode 100644
index 0000000000..94ddb45c90
--- /dev/null
+++ b/c/src/lib/libc/close.c
@@ -0,0 +1,70 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * 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 "libio_.h"
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+ int status;
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ int (*fp)(int fd);
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].close;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+ status = (*fp)( fd );
+ return status;
+ }
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+
+ if ( !iop->handlers )
+ set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->close )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->close)( iop );
+
+ rtems_libio_free( iop );
+
+ if (rc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( rc );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/c/src/lib/libc/closedir.c b/c/src/lib/libc/closedir.c
index 5edb3499e6..4d948ec95b 100644
--- a/c/src/lib/libc/closedir.c
+++ b/c/src/lib/libc/closedir.c
@@ -1,9 +1,44 @@
/*
* closedir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <dirent.h>
@@ -11,10 +46,25 @@
#include <unistd.h>
#include <errno.h>
-int closedir(
- register DIR *dirp
-)
+
+#include "libio_.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
{
- errno = ENOSYS;
- return -1;
+ int fd;
+
+ if ( !dirp )
+ set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
}
diff --git a/c/src/lib/libc/deviceio.c b/c/src/lib/libc/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/lib/libc/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * 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/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/lib/libc/dup.c b/c/src/lib/libc/dup.c
new file mode 100644
index 0000000000..c17db588a7
--- /dev/null
+++ b/c/src/lib/libc/dup.c
@@ -0,0 +1,23 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/c/src/lib/libc/dup2.c b/c/src/lib/libc/dup2.c
new file mode 100644
index 0000000000..5653425708
--- /dev/null
+++ b/c/src/lib/libc/dup2.c
@@ -0,0 +1,49 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+
+#include "libio_.h"
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/c/src/lib/libc/eval.c b/c/src/lib/libc/eval.c
new file mode 100644
index 0000000000..bf7dd1c126
--- /dev/null
+++ b/c/src/lib/libc/eval.c
@@ -0,0 +1,74 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * 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 "libio_.h"
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ result = (*pathloc->ops->evalpath)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( follow_link ) {
+
+ if ( !pathloc->ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ type = (*pathloc->ops->node_type)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->eval_link)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
diff --git a/c/src/lib/libc/fchmod.c b/c/src/lib/libc/fchmod.c
new file mode 100644
index 0000000000..a3ca4507ab
--- /dev/null
+++ b/c/src/lib/libc/fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * 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 <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "libio_.h"
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fchmod().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod)( &iop->pathinfo, mode );
+}
+
diff --git a/c/src/lib/libc/fcntl.c b/c/src/lib/libc/fcntl.c
new file mode 100644
index 0000000000..f6f33534ab
--- /dev/null
+++ b/c/src/lib/libc/fcntl.c
@@ -0,0 +1,111 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include "libio_.h"
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ va_list ap;
+ rtems_libio_t *iop;
+
+ va_start( ap, cmd );
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fcntl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ /*
+ * This is how it appears that this case should work:
+ *
+ * filedes2 = va_arg( ap, int )
+ * if filedes2 is 0
+ * duplicate fd into a new descriptor
+ * else
+ * duplicate fd into specified descriptor after error checking it
+ *
+ * See dup2() in case we can eliminate stuff in there.
+ */
+ return -1;
+
+ case F_GETFD: /* get f_flags */
+ if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
+ return 1;
+ return 0;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ return 0;
+
+ case F_GETFL: /* more flags (cloexec) */
+ return -1;
+
+ case F_SETFL:
+ return -1;
+
+ case F_GETLK:
+ return -1;
+
+ case F_SETLK:
+ return -1;
+
+ case F_SETLKW:
+ return -1;
+
+ case F_SETOWN: /* for sockets. */
+ return -1;
+
+ case F_GETOWN: /* for sockets. */
+ return -1;
+
+ default:
+ break;
+ }
+ return -1;
+}
diff --git a/c/src/lib/libc/fdatasync.c b/c/src/lib/libc/fdatasync.c
new file mode 100644
index 0000000000..58a4c4e118
--- /dev/null
+++ b/c/src/lib/libc/fdatasync.c
@@ -0,0 +1,45 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * 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 <unistd.h>
+
+#include "libio_.h"
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fdatasync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync)( iop );
+}
diff --git a/c/src/lib/libc/fpathconf.c b/c/src/lib/libc/fpathconf.c
new file mode 100644
index 0000000000..ea2377e15b
--- /dev/null
+++ b/c/src/lib/libc/fpathconf.c
@@ -0,0 +1,91 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * 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 "libio_.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then it is an error since fpathconf() is not included in the
+ * set.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the information request.
+ */
+
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_fd(fd);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/c/src/lib/libc/fstat.c b/c/src/lib/libc/fstat.c
new file mode 100644
index 0000000000..82d144dd2c
--- /dev/null
+++ b/c/src/lib/libc/fstat.c
@@ -0,0 +1,94 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * 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 <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "libio_.h"
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if (rtems_file_descriptor_type(fd)) {
+ switch (rtems_file_descriptor_type (fd)) {
+ case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
+ break;
+
+ case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
+#if !defined(__GO32__)
+ sbuf->st_mode = S_IFSOCK;
+ break;
+#endif
+
+ default:
+ set_errno_and_return_minus_one( EBADF );
+ }
+ }
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fstat)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/c/src/lib/libc/fsync.c b/c/src/lib/libc/fsync.c
new file mode 100644
index 0000000000..a5ed1e99e7
--- /dev/null
+++ b/c/src/lib/libc/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * 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 <unistd.h>
+
+#include "libio_.h"
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the fsync().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fsync )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync)( iop );
+}
diff --git a/c/src/lib/libc/ftruncate.c b/c/src/lib/libc/ftruncate.c
new file mode 100644
index 0000000000..7fb2286531
--- /dev/null
+++ b/c/src/lib/libc/ftruncate.c
@@ -0,0 +1,60 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * If this is not a file system based entity, it is an error.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) )
+ set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate)( iop, length );
+}
+
diff --git a/c/src/lib/libc/getdents.c b/c/src/lib/libc/getdents.c
index 9b16d82409..91631843b7 100644
--- a/c/src/lib/libc/getdents.c
+++ b/c/src/lib/libc/getdents.c
@@ -1,14 +1,59 @@
/*
- * Just enough to make newlib return an error.
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+
int getdents(
- int fd,
- void *buf,
- int len
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
)
{
- return -1;
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read)( iop, dd_buf, dd_len );
}
diff --git a/c/src/lib/libc/hosterr.c b/c/src/lib/libc/hosterr.c
index a55e4a7e84..6c0308df3b 100644
--- a/c/src/lib/libc/hosterr.c
+++ b/c/src/lib/libc/hosterr.c
@@ -13,31 +13,36 @@
*/
#include <rtems.h>
+#if defined(RTEMS_UNIX)
#include <errno.h>
-int host_errno(void);
+int host_errno( void );
/*
- * copy host errno, if any to thread aware errno, if any
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
*/
-void fix_syscall_errno(void)
+void fix_syscall_errno( void )
{
- errno = host_errno();
+ errno = host_errno();
}
/*
- * Get the host system errno, if any
- * When using newlib (or possibly other libc's) on top of UNIX
- * the errno returned by system calls may be unavailable due
- * to trickery of making errno thread aware.
- * This provides a kludge of getting at it.
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
*/
#undef errno
extern int errno;
int host_errno(void)
{
- return errno;
+ return errno;
}
-
+#endif
diff --git a/c/src/lib/libc/imfs.h b/c/src/lib/libc/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/lib/libc/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * 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$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libc/imfs_chown.c b/c/src/lib/libc/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/lib/libc/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_creat.c b/c/src/lib/libc/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/lib/libc/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * 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 <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/lib/libc/imfs_debug.c b/c/src/lib/libc/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/lib/libc/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * 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 <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/lib/libc/imfs_directory.c b/c/src/lib/libc/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/lib/libc/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/lib/libc/imfs_eval.c b/c/src/lib/libc/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/lib/libc/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/lib/libc/imfs_fchmod.c b/c/src/lib/libc/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/lib/libc/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_free.c b/c/src/lib/libc/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/lib/libc/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_getchild.c b/c/src/lib/libc/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/lib/libc/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * 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 <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_gtkn.c b/c/src/lib/libc/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/lib/libc/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * 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 <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/lib/libc/imfs_handlers.c b/c/src/lib/libc/imfs_handlers.c
new file mode 100644
index 0000000000..cd9cdcb435
--- /dev/null
+++ b/c/src/lib/libc/imfs_handlers.c
@@ -0,0 +1,93 @@
+/*
+ * Operations Tables for the IMFS
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Set of operations handlers for operations on memfile entities.
+ */
+
+rtems_filesystem_file_handlers_r memfile_handlers = {
+ memfile_open,
+ memfile_close,
+ memfile_read,
+ memfile_write,
+ memfile_ioctl,
+ memfile_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ memfile_ftruncate,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Set of operations handlers for operations on directories.
+ */
+
+rtems_filesystem_file_handlers_r dir_handlers = {
+ imfs_dir_open,
+ imfs_dir_close,
+ imfs_dir_read,
+ NULL,
+ NULL,
+ imfs_dir_lseek,
+ imfs_dir_fstat,
+ IMFS_fchmod,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Handler table for IMFS device nodes
+ */
+
+rtems_filesystem_file_handlers_r device_handlers = {
+ device_open,
+ device_close,
+ device_read,
+ device_write,
+ device_ioctl,
+ device_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Set of null operations handlers.
+ */
+
+rtems_filesystem_file_handlers_r null_handlers = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/c/src/lib/libc/imfs_init.c b/c/src/lib/libc/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/lib/libc/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/lib/libc/imfs_initsupp.c b/c/src/lib/libc/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/lib/libc/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/lib/libc/imfs_link.c b/c/src/lib/libc/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/lib/libc/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_mknod.c b/c/src/lib/libc/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/lib/libc/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/lib/libc/imfs_mount.c b/c/src/lib/libc/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/lib/libc/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_ntype.c b/c/src/lib/libc/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/lib/libc/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/lib/libc/imfs_readlink.c b/c/src/lib/libc/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/lib/libc/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/lib/libc/imfs_rmnod.c b/c/src/lib/libc/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/lib/libc/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/lib/libc/imfs_stat.c b/c/src/lib/libc/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/lib/libc/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_symlink.c b/c/src/lib/libc/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/lib/libc/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/lib/libc/imfs_unlink.c b/c/src/lib/libc/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/lib/libc/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/lib/libc/imfs_unmount.c b/c/src/lib/libc/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/lib/libc/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/imfs_utime.c b/c/src/lib/libc/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/lib/libc/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/internal.h b/c/src/lib/libc/internal.h
deleted file mode 100644
index 75b9f29633..0000000000
--- a/c/src/lib/libc/internal.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* internal.h
- *
- * This include file contains internal information
- * for the RTEMS C library support which is needed across
- * files.
- *
- * 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$
- */
-
-#ifndef __INTERNAL_LIBC_h
-#define __INTERNAL_LIBC_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void MY_task_set_note(
- rtems_tcb *tcb,
- rtems_unsigned32 notepad,
- rtems_unsigned32 note
-);
-
-rtems_unsigned32 MY_task_get_note(
- rtems_tcb *tcb,
- rtems_unsigned32 notepad
-);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-/* end of include file */
diff --git a/c/src/lib/libc/ioctl.c b/c/src/lib/libc/ioctl.c
new file mode 100644
index 0000000000..0aaf0379ae
--- /dev/null
+++ b/c/src/lib/libc/ioctl.c
@@ -0,0 +1,57 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * 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 "libio_.h"
+
+int ioctl(
+ int fd,
+ unsigned32 command,
+ void * buffer
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_ioctl_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].ioctl;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, command, buffer );
+ }
+
+ /*
+ * Now process the ioctl().
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+
+ if ( !iop->handlers->ioctl )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/c/src/lib/libc/ioman.c b/c/src/lib/libc/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/lib/libc/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
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;
}
diff --git a/c/src/lib/libc/libio.h b/c/src/lib/libc/libio.h
index dcdda85aec..76a90954b0 100644
--- a/c/src/lib/libc/libio.h
+++ b/c/src/lib/libc/libio.h
@@ -1,11 +1,18 @@
/*
- * General purpose communication channel for RTEMS to allow UNIX/POSIX
- * system call behavior on top of RTEMS IO devices.
+ * System call and file system interface definition
*
- * TODO
- * stat(2)
- * unlink(2)
- * rename(2)
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * 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$
*/
@@ -15,36 +22,342 @@
#include <sys/stat.h>
-typedef unsigned32 rtems_libio_offset_t;
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+typedef struct rtems_libio_tt rtems_libio_t;
+
+struct rtems_filesystem_location_info_tt;
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+/*
+ * Valid RTEMS file types.
+ */
+typedef enum {
+ RTEMS_FILESYSTEM_DIRECTORY,
+ RTEMS_FILESYSTEM_DEVICE,
+ RTEMS_FILESYSTEM_HARD_LINK,
+ RTEMS_FILESYSTEM_SYM_LINK,
+ RTEMS_FILESYSTEM_MEMORY_FILE
+} rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef struct {
+ rtems_filesystem_open_t open;
+ rtems_filesystem_close_t close;
+ rtems_filesystem_read_t read;
+ rtems_filesystem_write_t write;
+ rtems_filesystem_ioctl_t ioctl;
+ rtems_filesystem_lseek_t lseek;
+ rtems_filesystem_fstat_t fstat;
+ rtems_filesystem_fchmod_t fchmod;
+ rtems_filesystem_ftruncate_t ftruncate;
+ rtems_filesystem_fpathconf_t fpathconf;
+ rtems_filesystem_fsync_t fsync;
+ rtems_filesystem_fdatasync_t fdatasync;
+} rtems_filesystem_file_handlers_r;
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+typedef struct {
+ rtems_filesystem_evalpath_t evalpath;
+ rtems_filesystem_evalmake_t evalformake;
+ rtems_filesystem_link_t link;
+ rtems_filesystem_unlink_t unlink;
+ rtems_filesystem_node_type_t node_type;
+ rtems_filesystem_mknod_t mknod;
+ rtems_filesystem_rmnod_t rmnod;
+ rtems_filesystem_chown_t chown;
+ rtems_filesystem_freenode_t freenod;
+ rtems_filesystem_mount_t mount;
+ rtems_filesystem_fsmount_me_t fsmount_me;
+ rtems_filesystem_unmount_t unmount;
+ rtems_filesystem_fsunmount_me_t fsunmount_me;
+ rtems_filesystem_utime_t utime;
+ rtems_filesystem_evaluate_link_t eval_link;
+ rtems_filesystem_symlink_t symlink;
+ rtems_filesystem_readlink_t readlink;
+} rtems_filesystem_operations_table;
+
+#define IMFS_FILE_SYSTEM IMFS_ops
+extern rtems_filesystem_operations_table IMFS_ops;
+
/*
- * An open file data structure, indexed by 'fd'
- * TODO:
- * should really have a separate per/file data structure that this
- * points to (eg: size, offset, driver, pathname should be in that)
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
*/
typedef struct {
- rtems_driver_name_t *driver;
- rtems_libio_offset_t size; /* size of file */
- rtems_libio_offset_t offset; /* current offset into the file */
- unsigned32 flags;
- char *pathname; /* opened pathname */
- Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
- void *data1; /* ... */
-} rtems_libio_t;
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt{
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
/*
- * param block for read/write
- * Note: it must include 'offset' instead of using iop's offset since
- * we can have multiple outstanding i/o's on a device.
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE_ONLY,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ unsigned32 flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ unsigned32 data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
- rtems_libio_offset_t offset;
+ off_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
@@ -52,7 +365,7 @@ typedef struct {
} rtems_libio_rw_args_t;
/*
- * param block for open/close
+ * param block for open/close
*/
typedef struct {
@@ -62,7 +375,7 @@ typedef struct {
} rtems_libio_open_close_args_t;
/*
- * param block for ioctl
+ * param block for ioctl
*/
typedef struct {
@@ -72,9 +385,8 @@ typedef struct {
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
-
/*
- * Values for 'flag'
+ * Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
@@ -84,33 +396,72 @@ typedef struct {
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
-void rtems_libio_init(void);
-int __rtems_open(const char *pathname, unsigned32 flag, unsigned32 mode);
-int __rtems_close(int fd);
-int __rtems_read(int fd, void *buffer, unsigned32 count);
-int __rtems_write(int fd, const void *buffer, unsigned32 count);
-int __rtems_ioctl(int fd, unsigned32 command, void *buffer);
-int __rtems_lseek(int fd, rtems_libio_offset_t offset, int whence);
-int __rtems_fstat(int _fd, struct stat* _sbuf);
+void rtems_libio_init(void);
/*
- * External I/O handlers
+ * External I/O handlers
*/
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ unsigned32 count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ unsigned32 command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
typedef struct {
- int (*open)(const char *pathname, unsigned32 flag, unsigned32 mode);
- int (*close)(int fd);
- int (*read)(int fd, void *buffer, unsigned32 count);
- int (*write)(int fd, const void *buffer, unsigned32 count);
- int (*ioctl)(int fd, unsigned32 command, void *buffer);
- int (*lseek)(int fd, rtems_libio_offset_t offset, int whence);
+ rtems_libio_open_t open;
+ rtems_libio_close_t close;
+ rtems_libio_read_t read;
+ rtems_libio_write_t write;
+ rtems_libio_ioctl_t ioctl;
+ rtems_libio_lseek_t lseek;
} rtems_libio_handler_t;
-void rtems_register_libio_handler(int handler_flag,
- const rtems_libio_handler_t *handler);
+/*
+ * Register a set of external handlers
+ */
+
+void rtems_register_libio_handler(
+ int handler_flag,
+ const rtems_libio_handler_t *handler
+);
+
+/*
+ * Macros to assist in management of external IO handlers.
+ */
#define RTEMS_FILE_DESCRIPTOR_TYPE_FILE 0x0000
#define RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET 0x1000
@@ -128,39 +479,117 @@ void rtems_register_libio_handler(int handler_flag,
#define RTEMS_IO_TCDRAIN 3
/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = (rtems_device_major_number) ((_dev) >> 32); \
+ (_minor) = (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
* Callbacks from TERMIOS routines to device-dependent code
*/
+
#include <termios.h>
+
typedef struct rtems_termios_callbacks {
- int (*firstOpen)(int major, int minor, void *arg);
- int (*lastClose)(int major, int minor, void *arg);
- int (*pollRead)(int minor);
- int (*write)(int minor, const char *buf, int len);
- int (*setAttributes)(int minor, const struct termios *t);
- int (*stopRemoteTx)(int minor);
- int (*startRemoteTx)(int minor);
- int outputUsesInterrupts;
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
} rtems_termios_callbacks;
/*
- * Device-independent TERMIOS routines
+ * Device-independent TERMIOS routines
*/
+
void rtems_termios_initialize (void);
+
rtems_status_code rtems_termios_open (
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg,
const rtems_termios_callbacks *callbacks
- );
-rtems_status_code rtems_termios_close (void *arg);
-rtems_status_code rtems_termios_read (void *arg);
-rtems_status_code rtems_termios_write (void *arg);
-rtems_status_code rtems_termios_ioctl (void *arg);
-int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
-int rtems_termios_dequeue_characters (void *ttyp, int len);
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
void rtems_termios_reserve_resources(
rtems_configuration_table *configuration,
rtems_unsigned32 number_of_devices
);
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+);
+
#endif /* _RTEMS_LIBIO_H */
diff --git a/c/src/lib/libc/libio_.h b/c/src/lib/libc/libio_.h
new file mode 100644
index 0000000000..bb6f81f35a
--- /dev/null
+++ b/c/src/lib/libc/libio_.h
@@ -0,0 +1,248 @@
+/*
+ * Libio Internal Information
+ *
+ * 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$
+ */
+
+#ifndef __LIBIO__h
+#define __LIBIO__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <rtems/libio.h>
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <stdarg.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 */
+
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#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 rtems_id rtems_libio_semaphore;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern unsigned32 rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+
+/*
+ * External I/O Handlers Table
+ *
+ * Space for all possible handlers is preallocated
+ * to speed up dispatch to external handlers.
+ */
+
+extern rtems_libio_handler_t rtems_libio_handlers[15];
+
+/*
+ * Default mode for all files.
+ */
+
+extern mode_t rtems_filesystem_umask;
+
+/*
+ * set_errno_and_return_minus_one
+ *
+ * Macro to ease common way to return an error.
+ */
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((unsigned32)(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((unsigned32) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+extern rtems_filesystem_location_info_t rtems_filesystem_root;
+extern nlink_t rtems_filesystem_link_counts;
+
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+unsigned32 rtems_libio_fcntl_flags(
+ unsigned32 fcntl_flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
+
+
diff --git a/c/src/lib/libc/link.c b/c/src/lib/libc/link.c
new file mode 100644
index 0000000000..1cee54d0bf
--- /dev/null
+++ b/c/src/lib/libc/link.c
@@ -0,0 +1,60 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * 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/libio.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+ result = (*parent_loc.ops->evalformake)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 )
+ set_errno_and_return_minus_one( result );
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry )
+ set_errno_and_return_minus_one( EXDEV );
+
+ if ( !parent_loc.ops->link )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*parent_loc.ops->link)( &existing_loc, &parent_loc, name_start );
+}
diff --git a/c/src/lib/libc/lseek.c b/c/src/lib/libc/lseek.c
new file mode 100644
index 0000000000..514f8cd912
--- /dev/null
+++ b/c/src/lib/libc/lseek.c
@@ -0,0 +1,93 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * 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 <stdio.h>
+
+#include "libio_.h"
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_lseek_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].lseek;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, offset, whence );
+ }
+
+ /*
+ * Now process the lseek().
+ */
+
+ 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;
+ }
+
+ if ( !iop->handlers->lseek )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->lseek)( iop, offset, whence );
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
+
diff --git a/c/src/lib/libc/malloc.c b/c/src/lib/libc/malloc.c
index fac38585a7..f164e45f6c 100644
--- a/c/src/lib/libc/malloc.c
+++ b/c/src/lib/libc/malloc.c
@@ -135,7 +135,7 @@ void RTEMS_Malloc_Initialize(
#ifdef MALLOC_STATS
/* zero all the stats */
- (void) memset(&rtems_malloc_stats, 0, sizeof(rtems_malloc_stats));
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
#endif
MSBUMP(space_available, length);
@@ -220,9 +220,11 @@ void *malloc(
{
unsigned32 actual_size;
unsigned32 current_depth;
- status = rtems_region_get_segment_size(RTEMS_Malloc_Heap, return_this, &actual_size);
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
MSBUMP(lifetime_allocated, actual_size);
- current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
if (current_depth > rtems_malloc_stats.max_depth)
rtems_malloc_stats.max_depth = current_depth;
}
@@ -335,10 +337,12 @@ void free(
void malloc_dump(void)
{
- unsigned32 allocated = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed;
+ unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
printf("Malloc stats\n");
- printf(" avail:%uk allocated:%uk (%d%%) max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
(unsigned int) rtems_malloc_stats.space_available / 1024,
(unsigned int) allocated / 1024,
/* avoid float! */
diff --git a/c/src/lib/libc/memfile.c b/c/src/lib/libc/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/lib/libc/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/lib/libc/mkdir.c b/c/src/lib/libc/mkdir.c
new file mode 100644
index 0000000000..18fc7171c7
--- /dev/null
+++ b/c/src/lib/libc/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
+
diff --git a/c/src/lib/libc/mkfifo.c b/c/src/lib/libc/mkfifo.c
new file mode 100644
index 0000000000..6b3ece5650
--- /dev/null
+++ b/c/src/lib/libc/mkfifo.c
@@ -0,0 +1,25 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/c/src/lib/libc/mknod.c b/c/src/lib/libc/mknod.c
new file mode 100644
index 0000000000..4f83321ecd
--- /dev/null
+++ b/c/src/lib/libc/mknod.c
@@ -0,0 +1,60 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->mknod)( name_start, mode, dev, &temp_loc );
+}
diff --git a/c/src/lib/libc/mount.c b/c/src/lib/libc/mount.c
new file mode 100644
index 0000000000..fa8cebc3f9
--- /dev/null
+++ b/c/src/lib/libc/mount.c
@@ -0,0 +1,299 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libio_.h"
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+/*
+ * XXX
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+);
+
+int init_fs_mount_table( void );
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ char *fsoptions,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_options_t options;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Are the file system options valid?
+ */
+
+ options = get_file_system_options( fsoptions );
+ if ( options == RTEMS_FILESYSTEM_BAD_OPTIONS ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Is the file system type valid?
+ */
+
+ if ( fs_ops == NULL ){
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ temp_mt_entry = malloc( sizeof(rtems_filesystem_mount_table_entry_t) );
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if( device )
+ sprintf( temp_mt_entry->dev, "%s", device );
+ else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+ if ( rtems_filesystem_evaluate_path(
+ mount_point,
+ RTEMS_LIBIO_PERMS_RWX,
+ &temp_loc ,
+ TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( temp_loc.ops->node_type( &temp_loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( search_mt_for_mount_point( &temp_loc ) == FOUND ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry
+ */
+
+ temp_mt_entry->mt_point_node.node_access = temp_loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = temp_loc.handlers;
+ temp_mt_entry->mt_point_node.ops = temp_loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = temp_loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !temp_loc.ops->mount ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( temp_loc.ops->mount( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ }
+ else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( !fs_ops->fsmount_me ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( fs_ops->fsmount_me( temp_mt_entry ) )
+ goto cleanup_and_bail;
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * get_file_system_options
+ *
+ * This routine will determine is the text string that represents the options
+ * that are to be used to mount the file system are actually valid. If the
+ * options are valid the appropriate file system options type will be returned
+ * to the calling routine.
+ */
+
+rtems_filesystem_options_t get_file_system_options(
+ char *fsoptions
+)
+{
+ if ( strcmp( "RO", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_ONLY;
+ if ( strcmp( "RW", strupr( fsoptions ) ) == 0 )
+ return RTEMS_FILESYSTEM_READ_WRITE_ONLY;
+ else
+ return RTEMS_FILESYSTEM_BAD_OPTIONS;
+}
+
+
+
+/*
+ * search_mt_for_mount_point
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_point_node to the node describing the selected
+ * mount point.. If any of the mount table file system mount point nodes
+ * match the new file system selected mount point node, we are attempting
+ * to mount the new file system onto a node that already has a file system
+ * mounted to it. This is not a permitted operation.
+ */
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_point_node.node_access ==
+ location_of_mount_point->node_access )
+ return FOUND;
+ }
+ return NOT_FOUND;
+}
+
diff --git a/c/src/lib/libc/newlibc.c b/c/src/lib/libc/newlibc.c
index a6acc1c8d7..bea592a46e 100644
--- a/c/src/lib/libc/newlibc.c
+++ b/c/src/lib/libc/newlibc.c
@@ -1,21 +1,14 @@
-
/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
* COPYRIGHT (c) 1994 by Division Incorporated
*
* 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.
*
- * Description:
- * Implementation of hooks for the CYGNUS newlib libc
- * These hooks set things up so that:
- * '_REENT' is switched at task switch time.
- *
- *
- * TODO:
- *
- * NOTE:
- *
* $Id$
*
*/
@@ -47,7 +40,21 @@
#include <stdio.h>
#endif
-#include "internal.h"
+/*
+ * Private routines
+ */
+
+void MY_task_set_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad,
+ rtems_unsigned32 note
+);
+
+rtems_unsigned32 MY_task_get_note(
+ rtems_tcb *tcb,
+ rtems_unsigned32 notepad
+);
+
#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
@@ -304,7 +311,7 @@ libc_init(int reentrant)
rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
&libc_extension, &extension_id);
if (rc != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(rc);
+ rtems_fatal_error_occurred( rc );
libc_reentrant = reentrant;
}
@@ -353,11 +360,14 @@ int get_errno()
/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
#if !defined(RTEMS_UNIX) && !defined(_AM29K)
+#if !defined(pc386)
void _exit(int status)
{
libc_wrapup(); /* Why? XXX */
rtems_shutdown_executive(status);
}
+#endif
+
#else
void exit(int status)
@@ -426,4 +436,46 @@ unsigned int sleep(
#endif
+/*
+ * Newlib Interface Support
+ *
+ * Routines to Access Internal RTEMS Resources without violating
+ * kernel visibility.
+ *
+ */
+
+void MY_task_set_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad,
+ unsigned32 note
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( api )
+ api->Notepads[ notepad ] = note;
+}
+
+
+unsigned32 MY_task_get_note(
+ Thread_Control *the_thread,
+ unsigned32 notepad
+)
+{
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ return api->Notepads[ notepad ];
+}
+
+void *MY_CPU_Context_FP_start(
+ void *base,
+ unsigned32 offset
+)
+{
+ return _CPU_Context_Fp_start( base, offset );
+}
#endif
diff --git a/c/src/lib/libc/newlibif.c b/c/src/lib/libc/newlibif.c
deleted file mode 100644
index 8b995fed92..0000000000
--- a/c/src/lib/libc/newlibif.c
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/*
- * This file contains the glue which maps newlib system calls onto their
- * RTEMS implementations. This formerly was in the file
- * libgloss/rtems/iface.c which was installed as rtems.o. Merging this
- * into the RTEMS source tree minimizes the files which must be linked
- * to build an rtems application.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <reent.h>
-
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-int
-read(int fd,
- char *buf,
- int nbytes)
-{
- return __rtems_read(fd, buf, nbytes);
-}
-
-int
-write(int fd,
- char *buf,
- int nbytes)
-{
- return __rtems_write(fd, buf, nbytes);
-}
-
-int
-open(char *buf,
- int flags,
- int mode)
-{
- return __rtems_open(buf, flags, mode);
-}
-
-int
-close(int fd)
-{
- return __rtems_close(fd);
-}
-
-/*
- * lseek -- move read/write pointer. Since a serial port
- * is non-seekable, we return an error.
- */
-off_t
-lseek(int fd,
- off_t offset,
- int whence)
-{
- return __rtems_lseek(fd, offset, whence);
-}
-
-/*
- * fstat -- get status of a file. Since we have no file
- * system, we just return an error.
- */
-int
-fstat(int fd,
- struct stat *buf)
-{
- return __rtems_fstat(fd, buf);
-}
-
-/*
- * getpid and kill are provided directly by rtems
- */
-
-/*
- * ioctl -- IO control
- */
-
-int
-ioctl(int fd, int request, void *argp)
-{
- return __rtems_ioctl(fd,request,argp);
-}
-
-#endif
diff --git a/c/src/lib/libc/newlibifr.c b/c/src/lib/libc/newlibifr.c
deleted file mode 100644
index 5d870c91a6..0000000000
--- a/c/src/lib/libc/newlibifr.c
+++ /dev/null
@@ -1,103 +0,0 @@
-
-/*
- * This file contains the glue which maps newlib system calls onto their
- * RTEMS implementations. This formerly was in the file
- * libgloss/rtems/iface.c which was installed as rtems.o. Merging this
- * into the RTEMS source tree minimizes the files which must be linked
- * to build an rtems application.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <reent.h>
-
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-_ssize_t _read_r(
- struct _reent *ptr,
- int fd,
- void *buf,
- size_t nbytes
-)
-{
- return __rtems_read(fd, buf, nbytes);
-}
-
-long _write_r(
- struct _reent *ptr,
- int fd,
- const void *buf,
- size_t nbytes
-)
-{
- return __rtems_write(fd, buf, nbytes);
-}
-
-int _open_r(
- struct _reent *ptr,
- const char *buf,
- int flags,
- int mode
-)
-{
- return __rtems_open(buf, flags, mode);
-}
-
-int _close_r(
- struct _reent *ptr,
- int fd
-)
-{
- return __rtems_close(fd);
-}
-
-off_t _lseek_r(
- struct _reent *ptr,
- int fd,
- off_t offset,
- int whence
-)
-{
- return __rtems_lseek(fd, offset, whence);
-}
-
-int _stat_r(
- struct _reent *ptr,
- const char *path,
- struct stat *buf
-)
-{
- return stat(path, buf);
-}
-
-int _fstat_r(
- struct _reent *ptr,
- int fd,
- struct stat *buf
-)
-{
- return __rtems_fstat(fd, buf);
-}
-
-pid_t _getpid_r(struct _reent *ptr)
-{
- pid_t __getpid();
- return __getpid();
-}
-
-int _kill_r( struct _reent *ptr, pid_t pid, int sig )
-{
- int __kill();
- return __kill(pid, sig);
-}
-#endif
diff --git a/c/src/lib/libc/no_libc.c b/c/src/lib/libc/no_libc.c
index 5a58ba761c..4bd02c4b27 100644
--- a/c/src/lib/libc/no_libc.c
+++ b/c/src/lib/libc/no_libc.c
@@ -1,6 +1,4 @@
-
-/* no_libc.h
- *
+/*
* This file contains stubs for the reentrancy hooks when
* an unknown C library is used.
*
@@ -17,15 +15,15 @@
#include <rtems.h>
-#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
#include "libcsupport.h"
-#include "internal.h"
#include <stdlib.h> /* for free() */
-void
-libc_init(int reentrant)
+void libc_init(
+ int reentrant
+)
{
}
@@ -34,11 +32,15 @@ void libc_suspend_main(void)
}
-void libc_global_exit(rtems_unsigned32 code)
+void libc_global_exit(
+ rtems_unsigned32 code
+)
{
}
-void _exit(int status)
+void _exit(
+ int status
+)
{
}
diff --git a/c/src/lib/libc/open.c b/c/src/lib/libc/open.c
new file mode 100644
index 0000000000..4cdf5acf35
--- /dev/null
+++ b/c/src/lib/libc/open.c
@@ -0,0 +1,202 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * 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 "libio_.h"
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and eitehr the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * 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().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+
+ status = rtems_filesystem_evaluate_path( pathname, eval_flags, &temp_loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ goto done;
+ }
+
+ /*
+ * Fill in the file control block based on the temp_loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = temp_loc.handlers;
+ iop->file_info = temp_loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = temp_loc;
+
+ if ( !iop->handlers->open ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ set_errno_and_return_minus_one( rc );
+ }
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/c/src/lib/libc/opendir.c b/c/src/lib/libc/opendir.c
index e303eb28e5..f0e9488684 100644
--- a/c/src/lib/libc/opendir.c
+++ b/c/src/lib/libc/opendir.c
@@ -1,17 +1,85 @@
/*
* opendir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
-DIR *opendir(
- const char *name
-)
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
{
- return NULL;
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
}
diff --git a/c/src/lib/libc/pathconf.c b/c/src/lib/libc/pathconf.c
new file mode 100644
index 0000000000..e19d1329f4
--- /dev/null
+++ b/c/src/lib/libc/pathconf.c
@@ -0,0 +1,38 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/c/src/lib/libc/pipe.c b/c/src/lib/libc/pipe.c
new file mode 100644
index 0000000000..35dcf627bb
--- /dev/null
+++ b/c/src/lib/libc/pipe.c
@@ -0,0 +1,23 @@
+/*
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
+ *
+ * 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 <errno.h>
+
+int pipe(
+ int filsdes[2]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/c/src/lib/libc/read.c b/c/src/lib/libc/read.c
new file mode 100644
index 0000000000..150fe675ab
--- /dev/null
+++ b/c/src/lib/libc/read.c
@@ -0,0 +1,84 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * 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 "libio_.h"
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int read(
+ int fd,
+ void *buffer,
+ unsigned32 count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_read_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].read;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the read().
+ */
+
+ 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 );
+
+ if ( !iop->handlers->read )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/lib/libc/readdir.c b/c/src/lib/libc/readdir.c
index d592a62b99..f950d56171 100644
--- a/c/src/lib/libc/readdir.c
+++ b/c/src/lib/libc/readdir.c
@@ -1,14 +1,77 @@
/*
* readdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
#include <dirent.h>
-struct dirent *readdir(
- register DIR *dirp
-)
-{
- return NULL;
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
}
diff --git a/c/src/lib/libc/readlink.c b/c/src/lib/libc/readlink.c
new file mode 100644
index 0000000000..22de51e88f
--- /dev/null
+++ b/c/src/lib/libc/readlink.c
@@ -0,0 +1,43 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * 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 "libio_.h"
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if (!buf)
+ set_errno_and_return_minus_one( EFAULT );
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( !loc.ops->readlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->readlink)( &loc, buf, bufsize );
+}
diff --git a/c/src/lib/libc/rewinddir.c b/c/src/lib/libc/rewinddir.c
index c85e6fd4d0..04313a6042 100644
--- a/c/src/lib/libc/rewinddir.c
+++ b/c/src/lib/libc/rewinddir.c
@@ -1,7 +1,14 @@
/*
* rewinddir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/types.h>
@@ -15,6 +22,14 @@ void rewinddir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
+
}
diff --git a/c/src/lib/libc/rmdir.c b/c/src/lib/libc/rmdir.c
new file mode 100644
index 0000000000..6c0331087f
--- /dev/null
+++ b/c/src/lib/libc/rmdir.c
@@ -0,0 +1,56 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libio_.h"
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.ops->rmnod )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->rmnod)( &loc );
+}
diff --git a/c/src/lib/libc/scandir.c b/c/src/lib/libc/scandir.c
index 380415dd97..9ba1cb7bec 100644
--- a/c/src/lib/libc/scandir.c
+++ b/c/src/lib/libc/scandir.c
@@ -1,7 +1,50 @@
/*
* scandir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
@@ -9,15 +52,98 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-
-int scandir(
- const char *dirname,
- struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*dcomp)(const void *, const void *)
-)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d, *p, **names;
+ register size_t nitems;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1);
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+
+ nitems = 0;
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ return(-1); /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
{
- errno = ENOSYS;
- return -1;
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
}
diff --git a/c/src/lib/libc/seekdir.c b/c/src/lib/libc/seekdir.c
index e591adbb9f..80802b56c6 100644
--- a/c/src/lib/libc/seekdir.c
+++ b/c/src/lib/libc/seekdir.c
@@ -1,7 +1,14 @@
/*
* seekdir() - POSIX 1003.1b - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/param.h>
@@ -12,10 +19,20 @@
#include <errno.h>
void seekdir(
- DIR *dirp,
- long loc
+ DIR *dirp,
+ long loc
)
{
- errno = ENOSYS;
- return -1;
+ off_t status;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+
}
diff --git a/c/src/lib/libc/stat.c b/c/src/lib/libc/stat.c
new file mode 100644
index 0000000000..8ad7e61511
--- /dev/null
+++ b/c/src/lib/libc/stat.c
@@ -0,0 +1,79 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * 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>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int stat(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ return (*loc.handlers->fstat)( &loc, buf );
+}
+#endif
+
+/*
+ * _stat_r
+ *
+ * This is the Newlib dependent reentrant version of stat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _stat_r(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return stat( path, buf );
+}
+#endif
diff --git a/c/src/lib/libc/support.c b/c/src/lib/libc/support.c
deleted file mode 100644
index 85e6bb363f..0000000000
--- a/c/src/lib/libc/support.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Routines to Access Internal RTEMS Resources
- *
- * 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>
-
-void MY_task_set_note(
- Thread_Control *the_thread,
- unsigned32 notepad,
- unsigned32 note
-)
-{
- RTEMS_API_Control *api;
-
- api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
-
- if ( api )
- api->Notepads[ notepad ] = note;
-}
-
-
-unsigned32 MY_task_get_note(
- Thread_Control *the_thread,
- unsigned32 notepad
-)
-{
- RTEMS_API_Control *api;
-
- api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
-
- return api->Notepads[ notepad ];
-}
-
-void *MY_CPU_Context_FP_start(
- void *base,
- unsigned32 offset
-)
-{
- return _CPU_Context_Fp_start( base, offset );
-}
-
diff --git a/c/src/lib/libc/symlink.c b/c/src/lib/libc/symlink.c
new file mode 100644
index 0000000000..ca9673f51b
--- /dev/null
+++ b/c/src/lib/libc/symlink.c
@@ -0,0 +1,34 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * 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 "libio_.h"
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ return (*loc.ops->symlink)( &loc, actualpath, name_start);
+}
+
diff --git a/c/src/lib/libc/syscalls.c b/c/src/lib/libc/syscalls.c
deleted file mode 100644
index e97034ddba..0000000000
--- a/c/src/lib/libc/syscalls.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * RTEMS Fake System Calls
- *
- * This file contains "fake" versions of the system call routines
- * which are reference by many libc implementations. Once a routine
- * has been implemented in terms of RTEMS services, it should be
- * taken out of this file.
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h> /* only for puts */
-
-#include <rtems.h>
-#include <rtems/libio.h>
-
-#ifdef RTEMS_NEWLIB
-
-int __rtems_fstat(int _fd, struct stat* _sbuf)
-{
-#ifdef HAVE_BLKSIZE
- _sbuf->st_blksize = 0;
-#endif
-
- /*
- * For now assume stdin/stdout/stderr are always a TTY line
- *
- * From Eric Norum:
- *
- * The `fix' is not complete. It still doesn't properly handle
- * file descriptors for any files/devices other than the console
- * serial lines.....
- */
- if (_fd <= 2) {
- _sbuf->st_mode = S_IFCHR;
- } else {
- switch (rtems_file_descriptor_type (_fd)) {
- case RTEMS_FILE_DESCRIPTOR_TYPE_FILE:
- _sbuf->st_mode = S_IFREG;
- break;
-
- case RTEMS_FILE_DESCRIPTOR_TYPE_SOCKET:
-#if !defined(__GO32__)
- _sbuf->st_mode = S_IFSOCK;
- break;
-#endif
-
- default:
- puts( "__rtems_fstat -- unknown file descriptor type" );
- assert( 0 );
- }
- }
- return 0;
-}
-
-#if !defined(RTEMS_UNIX)
-int stat( const char *path, struct stat *buf )
-{
- if ( strncmp( "/dev/", path, 5 ) ) {
- return -1;
- }
- return __rtems_fstat( 0, buf );
-}
-
-int link( const char *existing, const char *new )
-{
- /* always fail */
- return -1;
-}
-
-int unlink( const char *path )
-{
- /* always fail */
- return -1;
-}
-
-char *getcwd( char *_buf, size_t _size)
-{
-/* assert( FALSE ); */
- errno = ENOSYS;
- return 0;
-}
-#endif
-
-#endif
diff --git a/c/src/lib/libc/tcattr.c b/c/src/lib/libc/tcattr.c
deleted file mode 100644
index aaa5ff6e6e..0000000000
--- a/c/src/lib/libc/tcattr.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcgetattr and tcsetattr.
- *
- * $Id$
- *
- */
-
-#include <rtems.h>
-#if defined(RTEMS_NEWLIB)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <termios.h>
-
-#include "internal.h"
-#include "libio.h"
-
-/*
- * tcgetattr/tcsetattr -- get/set attributes of a device.
- *
- * submitted by K.Shibuya
- */
-
-int
-tcgetattr(int fd, struct termios *tp)
-{
- return __rtems_ioctl(fd,RTEMS_IO_GET_ATTRIBUTES,tp);
-}
-
-int
-tcsetattr(int fd, int opt, struct termios *tp)
-{
- if(opt != TCSANOW)
- return -1;
- return __rtems_ioctl(fd,RTEMS_IO_SET_ATTRIBUTES,tp);
-}
-
-#endif
diff --git a/c/src/lib/libc/tcdrain.c b/c/src/lib/libc/tcdrain.c
index 585871cc90..c2749a90e1 100644
--- a/c/src/lib/libc/tcdrain.c
+++ b/c/src/lib/libc/tcdrain.c
@@ -1,9 +1,15 @@
/*
- * This file contains the RTEMS implementation of the POSIX API
- * routines tcdrain.
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
*
- * $Id$
+ * 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>
@@ -13,14 +19,15 @@
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>
+#include <sys/ioctl.h>
-#include "internal.h"
#include "libio.h"
-int
-tcdrain(int fd)
+int tcdrain(
+ int fd
+)
{
- return __rtems_ioctl(fd,RTEMS_IO_TCDRAIN,0);
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
}
#endif
diff --git a/c/src/lib/libc/tcgetattr.c b/c/src/lib/libc/tcgetattr.c
new file mode 100644
index 0000000000..2d3e4d7e3c
--- /dev/null
+++ b/c/src/lib/libc/tcgetattr.c
@@ -0,0 +1,33 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/lib/libc/tcsetattr.c b/c/src/lib/libc/tcsetattr.c
new file mode 100644
index 0000000000..c0ed509a0f
--- /dev/null
+++ b/c/src/lib/libc/tcsetattr.c
@@ -0,0 +1,38 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * 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>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libio.h"
+#include "libio_.h"
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ if ( opt != TCSANOW )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/c/src/lib/libc/telldir.c b/c/src/lib/libc/telldir.c
index eee8d925ec..cea6cc08cb 100644
--- a/c/src/lib/libc/telldir.c
+++ b/c/src/lib/libc/telldir.c
@@ -1,7 +1,14 @@
/*
* telldir() - XXX
*
- * $Id$
+ * 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.
+ *
*/
#include <sys/param.h>
@@ -9,15 +16,24 @@
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
-#include <rtems.h>
-#include "libio.h"
+#include "libio_.h"
+
long telldir(
DIR *dirp
)
{
- errno = ENOSYS;
- return -1;
+ rtems_libio_t *iop;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
}
diff --git a/c/src/lib/libc/truncate.c b/c/src/lib/libc/truncate.c
new file mode 100644
index 0000000000..145e596654
--- /dev/null
+++ b/c/src/lib/libc/truncate.c
@@ -0,0 +1,41 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
+
diff --git a/c/src/lib/libc/umask.c b/c/src/lib/libc/umask.c
new file mode 100644
index 0000000000..35229a30a1
--- /dev/null
+++ b/c/src/lib/libc/umask.c
@@ -0,0 +1,30 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include "libio_.h"
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/c/src/lib/libc/unixlibc.c b/c/src/lib/libc/unixlibc.c
index 3e757e313d..a581d95534 100644
--- a/c/src/lib/libc/unixlibc.c
+++ b/c/src/lib/libc/unixlibc.c
@@ -1,5 +1,15 @@
/*
* $Id$
+ * UNIX Port C Library Support
+ *
+ * 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.
+ *
*/
#include <rtems.h>
diff --git a/c/src/lib/libc/unlink.c b/c/src/lib/libc/unlink.c
new file mode 100644
index 0000000000..d4a5520bcb
--- /dev/null
+++ b/c/src/lib/libc/unlink.c
@@ -0,0 +1,44 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ set_errno_and_return_minus_one( EISDIR );
+
+ if ( !loc.ops->unlink )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*loc.ops->unlink)( &loc );
+}
diff --git a/c/src/lib/libc/unmount.c b/c/src/lib/libc/unmount.c
new file mode 100644
index 0000000000..f50e63ff42
--- /dev/null
+++ b/c/src/lib/libc/unmount.c
@@ -0,0 +1,214 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+extern rtems_filesystem_location_info_t rtems_filesystem_current;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+);
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a mount_path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *mount_path
+)
+{
+ int status;
+ rtems_filesystem_location_info_t temp_loc;
+ rtems_filesystem_mount_table_entry_t temp_mt_entry;
+ int result;
+
+ /*
+ * Are there any file systems below the mount_path specified
+ */
+
+ status = file_systems_below_this_mountpoint(
+ mount_path,
+ &temp_loc,
+ &temp_mt_entry
+ );
+
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Is the current node reference pointing to a node in the file system
+ * we are attempting to unmount ?
+ */
+
+ if ( rtems_filesystem_current.mt_entry == temp_loc.mt_entry )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( temp_loc.mt_entry ) == 1 )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being mounted on to do its cleanup.
+ * XXX - Did I change these correctly ??? It looks like either I did
+ * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped.
+ * XXX Add to the mt_point_node unmount to set the mt_entry back to null
+ * XXX I will step off in space when evaluating past the end of the node.
+ */
+
+ if ( ( temp_mt_entry.mt_point_node.ops->unmount )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Run the unmount function for the subordinate file system.
+ */
+
+ if ( ( temp_mt_entry.mt_fs_root.ops->fsunmount_me )( temp_loc.mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the file system to clean up.
+ */
+
+ result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry );
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) temp_loc.mt_entry );
+
+ /*
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ free( temp_loc.mt_entry );
+
+ return result;
+
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+int file_systems_below_this_mountpoint(
+ const char *mount_path,
+ rtems_filesystem_location_info_t *temp_loc,
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+ rtems_filesystem_mount_table_entry_t *current_fs_mt_entry;
+
+ /*
+ * Is the mount_path even a valid node name in the existing tree?
+ */
+
+ if ( rtems_filesystem_evaluate_path( mount_path, 0x0, temp_loc, TRUE ) )
+ return -1;
+
+ /*
+ * Look for the node defined in temp_loc as a mount point in the
+ * mount table chain.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.node_access ==
+ temp_loc->node_access ) {
+ current_fs_mt_entry = the_mount_entry;
+ *temp_loc = current_fs_mt_entry->mt_fs_root;
+ goto after_real_mount_point_found;
+ }
+ }
+ set_errno_and_return_minus_one( EACCES );
+
+
+after_real_mount_point_found:
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+
+ /*
+ * Exclude the current file systems mount table entry from the test
+ */
+
+ if ( current_fs_mt_entry != the_mount_entry ) {
+ if ( the_mount_entry->mt_point_node.mt_entry == current_fs_mt_entry ) {
+
+ /*
+ * There is at least one fs below the fs on the mount_path.
+ */
+ set_errno_and_return_minus_one( EBUSY );
+ }
+ }
+ }
+
+ *temp_mt_entry = *current_fs_mt_entry;
+
+ return 0;
+}
diff --git a/c/src/lib/libc/utime.c b/c/src/lib/libc/utime.c
new file mode 100644
index 0000000000..f1a12ee1b2
--- /dev/null
+++ b/c/src/lib/libc/utime.c
@@ -0,0 +1,35 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * 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 <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include "libio_.h"
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*temp_loc.ops->utime)( &temp_loc, times->actime, times->modtime );
+}
diff --git a/c/src/lib/libc/write.c b/c/src/lib/libc/write.c
new file mode 100644
index 0000000000..7e0953bb90
--- /dev/null
+++ b/c/src/lib/libc/write.c
@@ -0,0 +1,92 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * 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 "libio_.h"
+
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+/* XXX newlib has the prototype for this wrong. It will be a bit painful */
+/* XXX to fix so we are choosing to delay fixing this. */
+
+int write( /* XXX this should return a ssize_t */
+ int fd,
+ const void *buffer,
+ unsigned32 count /* XXX this should be a size_t */
+)
+{
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+
+ /*
+ * If this file descriptor is mapped to an external set of handlers,
+ * then pass the request on to them.
+ */
+
+ if ( rtems_file_descriptor_type( fd ) ) {
+ rtems_libio_write_t fp;
+
+ fp = rtems_libio_handlers[rtems_file_descriptor_type_index(fd)].write;
+ if ( fp == NULL )
+ set_errno_and_return_minus_one( EBADF );
+
+ return (*fp)( fd, buffer, count );
+ }
+
+ /*
+ * Now process the write() request.
+ */
+
+ 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 );
+
+ if ( !iop->handlers->write )
+ set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+long _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/c/src/lib/libchip/serial/ns16550.c b/c/src/lib/libchip/serial/ns16550.c
index 918e87bf8c..6cb0714c32 100644
--- a/c/src/lib/libchip/serial/ns16550.c
+++ b/c/src/lib/libchip/serial/ns16550.c
@@ -424,6 +424,7 @@ NS16550_STATIC int ns16550_set_attributes(
rtems_interrupt_enable(Irql);
+ return 0;
}
/*
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c
index 918e87bf8c..6cb0714c32 100644
--- a/c/src/libchip/serial/ns16550.c
+++ b/c/src/libchip/serial/ns16550.c
@@ -424,6 +424,7 @@ NS16550_STATIC int ns16550_set_attributes(
rtems_interrupt_enable(Irql);
+ return 0;
}
/*
diff --git a/c/src/libfs/src/imfs/deviceio.c b/c/src/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..f954decf6e
--- /dev/null
+++ b/c/src/libfs/src/imfs/deviceio.c
@@ -0,0 +1,215 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * 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/libio.h>
+
+#include "imfs.h"
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return RTEMS_UNSATISFIED;
+
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+int device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+int device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return -1;
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * This IMFS_stat() is used.
+ */
diff --git a/c/src/libfs/src/imfs/imfs.h b/c/src/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..6eb535527d
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs.h
@@ -0,0 +1,445 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * 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$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 64 /* 512 */
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_MEMORY_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+} IMFS_types_union;
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->st_mtime = (time_t) tv.tv_sec; \
+ _jnode->st_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+} IMFS_fs_info_t;
+
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ set_errno_and_return_minus_one( ELOOP )
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r device_handlers;
+extern rtems_filesystem_file_handlers_r memfile_handlers;
+extern rtems_filesystem_file_handlers_r dir_handlers;
+extern rtems_filesystem_file_handlers_r null_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+int imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+int memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ unsigned32 flag, /* IN */
+ unsigned32 mode /* IN */
+);
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+int device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ unsigned32 count /* IN */
+);
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ unsigned32 command, /* IN */
+ void *buffer /* IN */
+);
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/libfs/src/imfs/imfs_chown.c b/c/src/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..816294ee34
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,52 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_creat.c b/c/src/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..fd38e7f993
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,130 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * 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 <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->st_atime = (time_t) tv.tv_sec;
+ node->st_mtime = (time_t) tv.tv_sec;
+ node->st_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/c/src/libfs/src/imfs/imfs_debug.c b/c/src/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..856f21317e
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,160 @@
+/*
+ * IMFS debug support routines
+ *
+ * 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 <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ printf( "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ printf( "/" );
+ break;
+
+ case IMFS_DEVICE:
+ printf( " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ printf( " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+ break;
+
+ case IMFS_HARD_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ printf( " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ printf( " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ printf( " " );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ printf( "*************** Dump of Entire IMFS ***************\n" );
+ printf( "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ printf( "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/c/src/libfs/src/imfs/imfs_directory.c b/c/src/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..134204027a
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,278 @@
+/*
+ * XXX
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+long getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/* -----------------------------------------------------------------------
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+int imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for(
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_ino = 1;
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ sprintf( tmp_dirent.d_name, "%s", the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /* The generic close routine handles the deallocation of the file control */
+ /* and associated memory. At present the imfs_dir_close simply */
+ /* returns a successful completion status */
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ off_t normal_offset;
+
+ normal_offset = (offset/sizeof(struct dirent)) * sizeof(struct dirent);
+
+
+ switch( whence )
+ {
+ case SEEK_SET: /* absolute move from the start of the file */
+ iop->offset = normal_offset;
+ break;
+
+ case SEEK_CUR: /* relative move */
+ iop->offset = iop->offset + normal_offset;
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * st_atime time of last access
+ * st_mtime time of last modification
+ * st_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_eval.c b/c/src/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..eb770a58ce
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,638 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = &dir_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &null_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = &memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( node, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if (! IMFS_is_separator( path[ i ] ) )
+ set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if (! rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if (! IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Only return root node if this is the base file system.
+ */
+
+ if ((pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) &&
+ (pathloc->node_access != rtems_filesystem_root.node_access) ) {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ }
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if (! IMFS_evaluate_permission( pathloc, flags ) )
+ set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_fchmod.c b/c/src/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..06c2969100
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,55 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ set_errno_and_return_minus_one( EPERM );
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_free.c b/c/src/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..8216547c12
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,99 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * 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 <errno.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
+
+
+/*
+ * IMFS_freenod
+ *
+ * The following routine frees a node if possible.
+ *
+ * The routine returns 0 if the node was not freed and 1 if it was.
+ *
+ * NOTE: This routine is for INTERNAL IMFS use only.
+ */
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ return ENOTEMPTY;
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ return EBUSY;
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ return EBUSY;
+ }
+
+ if ( !rtems_libio_is_file_open( the_jnode ) &&
+ (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+ if ( rtems_filesystem_current.node_access == pathloc->node_access ) {
+ rtems_filesystem_current.node_access = NULL;
+ }
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_getchild.c b/c/src/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..3f37738ab4
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * 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 <errno.h>
+#include <assert.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[2] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_gtkn.c b/c/src/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..052c67ceba
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * 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 <stdlib.h>
+#include "imfs.h"
+#include "libio_.h"
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+
+ while ( !IMFS_is_separator( path[i] ) && (i <= NAME_MAX) ) {
+
+ token[i] = path[i];
+
+ if (i == NAME_MAX)
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char( token[i] ) )
+ type = IMFS_INVALID_TOKEN;
+
+ i++;
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = path[i];
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/c/src/libfs/src/imfs/imfs_init.c b/c/src/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_initsupp.c b/c/src/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..bb3a0f9aea
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,158 @@
+/*
+ * IMFS Initialization
+ *
+ * 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 <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_rmnod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IRWXO | S_IRWXG| S_IRWXU ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = &dir_handlers;
+ temp_mt_entry->mt_fs_root.ops = &IMFS_ops;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ return 1;
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
+
+
+
diff --git a/c/src/libfs/src/imfs/imfs_link.c b/c/src/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..2232209705
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,72 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_mknod.c b/c/src/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..d4feef4f36
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,76 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ assert( 0 );
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
diff --git a/c/src/libfs/src/imfs/imfs_mount.c b/c/src/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..a267b52576
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,49 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_ntype.c b/c/src/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..bdf451a879
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/c/src/libfs/src/imfs/imfs_readlink.c b/c/src/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..958118f42f
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,40 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/c/src/libfs/src/imfs/imfs_rmnod.c b/c/src/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..f651622de4
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,97 @@
+/*
+ * IMFS_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "libio_.h"
+#include "imfs.h"
+
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ if ( the_jnode->type == IMFS_DIRECTORY ) {
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ set_errno_and_return_minus_one( EBUSY );
+ }
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ if ( the_jnode->type == IMFS_MEMORY_FILE )
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_stat.c b/c/src/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..4628736714
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,59 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ default:
+ set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->st_atime;
+ buf->st_mtime = the_jnode->st_mtime;
+ buf->st_ctime = the_jnode->st_ctime;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_symlink.c b/c/src/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..0d3ebbd670
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,60 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * 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 <errno.h>
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+
diff --git a/c/src/libfs/src/imfs/imfs_unlink.c b/c/src/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..4e0ca26b2a
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,67 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+
+ /*
+ * If this is the last referance to the node
+ * Free the node that the link points to.
+ */
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ if ( node->info.hard_link.link_node->st_nlink < 1) {
+ result = IMFS_rmnod( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ }
+
+ result = IMFS_rmnod( loc );
+
+ return result;
+}
diff --git a/c/src/libfs/src/imfs/imfs_unmount.c b/c/src/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..f29d720ab3
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,58 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * 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 <errno.h>
+
+#include "imfs.h"
+#include "libio_.h"
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/imfs_utime.c b/c/src/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..bc2639ef8c
--- /dev/null
+++ b/c/src/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,38 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * 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 <errno.h>
+#include <sys/time.h>
+
+#include "libio_.h"
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->st_atime = actime;
+ the_jnode->st_mtime = modtime;
+
+ return 0;
+}
diff --git a/c/src/libfs/src/imfs/ioman.c b/c/src/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..f8b725e987
--- /dev/null
+++ b/c/src/libfs/src/imfs/ioman.c
@@ -0,0 +1,83 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include "libio_.h"
+#include "imfs.h"
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is not reentrant.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t **device_info
+)
+{
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t temp_loc;
+ static rtems_driver_name_t device;
+ int result;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &temp_loc, TRUE );
+ the_jnode = temp_loc.node_access;
+
+ if ( (result != 0) || the_jnode->type != IMFS_DEVICE ) {
+ *device_info = 0;
+ return RTEMS_UNSATISFIED;
+ }
+
+ device.device_name = (char *) name;
+ device.device_name_length = strlen( name );
+ device.major = the_jnode->info.device.major;
+ device.minor = the_jnode->info.device.minor;
+ *device_info = &device;
+ return RTEMS_SUCCESSFUL;
+
+}
diff --git a/c/src/libfs/src/imfs/memfile.c b/c/src/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..01aee443f3
--- /dev/null
+++ b/c/src/libfs/src/imfs/memfile.c
@@ -0,0 +1,1000 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include "libio_.h"
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ unsigned32 flag,
+ unsigned32 mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+int memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ unsigned32 count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ unsigned32 command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ return 0;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ printf( "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ assert( memory );
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC int IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+printf( "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+printf( "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+printf( "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_blocK
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+printf( "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
diff --git a/c/src/tests/sptests/spsize/size.c b/c/src/tests/sptests/spsize/size.c
index 97281c9ee3..d12ff93305 100644
--- a/c/src/tests/sptests/spsize/size.c
+++ b/c/src/tests/sptests/spsize/size.c
@@ -30,8 +30,10 @@
#include <rtems/rtems/intr.h>
#include <rtems/io.h>
#include <rtems/rtems/message.h>
+#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/rtems/mp.h>
#include <rtems/score/mpci.h>
+#endif
#include <rtems/rtems/part.h>
#include <rtems/score/priority.h>
#include <rtems/rtems/ratemon.h>
@@ -105,12 +107,22 @@
#define MPCI_RECEIVE_SERVER_STACK_SIZE 0
#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#define MP_SYSTEM_TASKS \
+ (MPCI_RECEIVE_SERVER_STACK_SIZE + \
+ sizeof(Thread_Control) + \
+ MPCI_RECEIVE_SERVER_FP)
+#else
+#define MP_SYSTEM_TASKS 0
+#endif
+
+/*
+ * Idle and the MPCI Receive Server Threads
+ */
+
#define SYSTEM_TASKS \
- (STACK_MINIMUM_SIZE + \
- MPCI_RECEIVE_SERVER_STACK_SIZE + \
- (2*sizeof(Thread_Control))) + \
- MPCI_RECEIVE_SERVER_FP + \
- SYSTEM_IDLE_FP
+ (STACK_MINIMUM_SIZE + sizeof(Thread_Control) + SYSTEM_IDLE_FP + \
+ MP_SYSTEM_TASKS)
#define rtems_unsigned32 unsigned32