summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libcsupport/src')
-rw-r--r--cpukit/libcsupport/src/CASES23
-rw-r--r--cpukit/libcsupport/src/README37
-rw-r--r--cpukit/libcsupport/src/TODO14
-rw-r--r--cpukit/libcsupport/src/__assert.c52
-rw-r--r--cpukit/libcsupport/src/__getpid.c17
-rw-r--r--cpukit/libcsupport/src/__gettod.c86
-rw-r--r--cpukit/libcsupport/src/__times.c114
-rw-r--r--cpukit/libcsupport/src/__usrenv.c27
-rw-r--r--cpukit/libcsupport/src/_calloc_r.c30
-rw-r--r--cpukit/libcsupport/src/_free_r.c29
-rw-r--r--cpukit/libcsupport/src/_malloc_r.c29
-rw-r--r--cpukit/libcsupport/src/_realloc_r.c30
-rw-r--r--cpukit/libcsupport/src/_rename_r.c113
-rw-r--r--cpukit/libcsupport/src/access.c48
-rw-r--r--cpukit/libcsupport/src/assoclocalbyname.c31
-rw-r--r--cpukit/libcsupport/src/assoclocalbyremote.c31
-rw-r--r--cpukit/libcsupport/src/assoclocalbyremotebitfield.c34
-rw-r--r--cpukit/libcsupport/src/assocnamebad.c40
-rw-r--r--cpukit/libcsupport/src/assocnamebylocal.c31
-rw-r--r--cpukit/libcsupport/src/assocnamebylocalbitfield.c38
-rw-r--r--cpukit/libcsupport/src/assocnamebyremote.c33
-rw-r--r--cpukit/libcsupport/src/assocnamebyremotebitfield.c39
-rw-r--r--cpukit/libcsupport/src/assocptrbylocal.c34
-rw-r--r--cpukit/libcsupport/src/assocptrbyname.c35
-rw-r--r--cpukit/libcsupport/src/assocptrbyremote.c34
-rw-r--r--cpukit/libcsupport/src/assocremotebylocal.c31
-rw-r--r--cpukit/libcsupport/src/assocremotebylocalbitfield.c33
-rw-r--r--cpukit/libcsupport/src/assocremotebyname.c31
-rw-r--r--cpukit/libcsupport/src/base_fs.c114
-rw-r--r--cpukit/libcsupport/src/calloc.c41
-rw-r--r--cpukit/libcsupport/src/cfgetispeed.c32
-rw-r--r--cpukit/libcsupport/src/cfgetospeed.c32
-rw-r--r--cpukit/libcsupport/src/cfsetispeed.c40
-rw-r--r--cpukit/libcsupport/src/cfsetospeed.c40
-rw-r--r--cpukit/libcsupport/src/chdir.c57
-rw-r--r--cpukit/libcsupport/src/chmod.c46
-rw-r--r--cpukit/libcsupport/src/chown.c54
-rw-r--r--cpukit/libcsupport/src/chroot.c55
-rw-r--r--cpukit/libcsupport/src/close.c57
-rw-r--r--cpukit/libcsupport/src/ctermid.c42
-rw-r--r--cpukit/libcsupport/src/dup.c26
-rw-r--r--cpukit/libcsupport/src/dup2.c52
-rw-r--r--cpukit/libcsupport/src/envlock.c108
-rw-r--r--cpukit/libcsupport/src/error.c209
-rw-r--r--cpukit/libcsupport/src/eval.c151
-rw-r--r--cpukit/libcsupport/src/fchdir.c82
-rw-r--r--cpukit/libcsupport/src/fchmod.c45
-rw-r--r--cpukit/libcsupport/src/fchown.c42
-rw-r--r--cpukit/libcsupport/src/fcntl.c184
-rw-r--r--cpukit/libcsupport/src/fdatasync.c39
-rw-r--r--cpukit/libcsupport/src/flockfile.c22
-rw-r--r--cpukit/libcsupport/src/fpathconf.c87
-rw-r--r--cpukit/libcsupport/src/free.c55
-rw-r--r--cpukit/libcsupport/src/freenode.c20
-rw-r--r--cpukit/libcsupport/src/fstat.c72
-rw-r--r--cpukit/libcsupport/src/fsync.c39
-rw-r--r--cpukit/libcsupport/src/ftruncate.c51
-rw-r--r--cpukit/libcsupport/src/ftrylockfile.c25
-rw-r--r--cpukit/libcsupport/src/funlockfile.c22
-rw-r--r--cpukit/libcsupport/src/getchark.c25
-rw-r--r--cpukit/libcsupport/src/getcwd.c291
-rw-r--r--cpukit/libcsupport/src/getdents.c55
-rw-r--r--cpukit/libcsupport/src/getegid.c24
-rw-r--r--cpukit/libcsupport/src/geteuid.c31
-rw-r--r--cpukit/libcsupport/src/getgid.c18
-rw-r--r--cpukit/libcsupport/src/getgroups.c23
-rw-r--r--cpukit/libcsupport/src/getlogin.c61
-rw-r--r--cpukit/libcsupport/src/getpagesize.c22
-rw-r--r--cpukit/libcsupport/src/getpgrp.c31
-rw-r--r--cpukit/libcsupport/src/getpid.c41
-rw-r--r--cpukit/libcsupport/src/getppid.c25
-rw-r--r--cpukit/libcsupport/src/getpwent.c438
-rw-r--r--cpukit/libcsupport/src/getrusage.c54
-rw-r--r--cpukit/libcsupport/src/getuid.c28
-rw-r--r--cpukit/libcsupport/src/gxx_wrappers.c295
-rw-r--r--cpukit/libcsupport/src/ioctl.c54
-rw-r--r--cpukit/libcsupport/src/isatty.c35
-rw-r--r--cpukit/libcsupport/src/isatty_r.c35
-rw-r--r--cpukit/libcsupport/src/issetugid.c16
-rw-r--r--cpukit/libcsupport/src/kill_noposix.c48
-rw-r--r--cpukit/libcsupport/src/lchown.c31
-rw-r--r--cpukit/libcsupport/src/libio.c278
-rw-r--r--cpukit/libcsupport/src/libio_init.c89
-rw-r--r--cpukit/libcsupport/src/libio_sockets.c73
-rw-r--r--cpukit/libcsupport/src/link.c94
-rw-r--r--cpukit/libcsupport/src/lseek.c94
-rw-r--r--cpukit/libcsupport/src/lstat.c22
-rw-r--r--cpukit/libcsupport/src/malloc.c83
-rw-r--r--cpukit/libcsupport/src/malloc_deferred.c60
-rw-r--r--cpukit/libcsupport/src/malloc_dirtier.c30
-rw-r--r--cpukit/libcsupport/src/malloc_get_statistics.c33
-rw-r--r--cpukit/libcsupport/src/malloc_initialize.c114
-rw-r--r--cpukit/libcsupport/src/malloc_p.h45
-rw-r--r--cpukit/libcsupport/src/malloc_report_statistics.c26
-rw-r--r--cpukit/libcsupport/src/malloc_report_statistics_plugin.c61
-rw-r--r--cpukit/libcsupport/src/malloc_sbrk_helpers.c112
-rw-r--r--cpukit/libcsupport/src/malloc_statistics_helpers.c75
-rw-r--r--cpukit/libcsupport/src/malloc_walk.c28
-rw-r--r--cpukit/libcsupport/src/mallocfreespace.c42
-rw-r--r--cpukit/libcsupport/src/mallocgetheapptr.c26
-rw-r--r--cpukit/libcsupport/src/mallocinfo.c39
-rw-r--r--cpukit/libcsupport/src/mallocsetheapptr.c28
-rw-r--r--cpukit/libcsupport/src/mkdir.c30
-rw-r--r--cpukit/libcsupport/src/mkfifo.c28
-rw-r--r--cpukit/libcsupport/src/mknod.c73
-rw-r--r--cpukit/libcsupport/src/mount-mgr.c169
-rw-r--r--cpukit/libcsupport/src/mount-mktgt.c56
-rw-r--r--cpukit/libcsupport/src/mount.c282
-rw-r--r--cpukit/libcsupport/src/newlibc_exit.c160
-rw-r--r--cpukit/libcsupport/src/newlibc_init.c41
-rw-r--r--cpukit/libcsupport/src/newlibc_reent.c170
-rw-r--r--cpukit/libcsupport/src/open.c215
-rw-r--r--cpukit/libcsupport/src/open_dev_console.c51
-rw-r--r--cpukit/libcsupport/src/pathconf.c41
-rw-r--r--cpukit/libcsupport/src/pipe.c32
-rw-r--r--cpukit/libcsupport/src/posix_memalign.c44
-rw-r--r--cpukit/libcsupport/src/printk.c39
-rw-r--r--cpukit/libcsupport/src/printk_plugin.c34
-rw-r--r--cpukit/libcsupport/src/privateenv.c204
-rw-r--r--cpukit/libcsupport/src/putk.c30
-rw-r--r--cpukit/libcsupport/src/read.c67
-rw-r--r--cpukit/libcsupport/src/readdir_r.c30
-rw-r--r--cpukit/libcsupport/src/readlink.c48
-rw-r--r--cpukit/libcsupport/src/readv.c120
-rw-r--r--cpukit/libcsupport/src/realloc.c88
-rw-r--r--cpukit/libcsupport/src/rmdir.c95
-rw-r--r--cpukit/libcsupport/src/rtems_heap_extend.c45
-rw-r--r--cpukit/libcsupport/src/rtems_malloc.c56
-rw-r--r--cpukit/libcsupport/src/rtems_memalign.c72
-rw-r--r--cpukit/libcsupport/src/rtems_mkdir.c141
-rw-r--r--cpukit/libcsupport/src/setegid.c26
-rw-r--r--cpukit/libcsupport/src/seteuid.c24
-rw-r--r--cpukit/libcsupport/src/setgid.c21
-rw-r--r--cpukit/libcsupport/src/setpgid.c24
-rw-r--r--cpukit/libcsupport/src/setsid.c21
-rw-r--r--cpukit/libcsupport/src/setuid.c30
-rw-r--r--cpukit/libcsupport/src/stat.c97
-rw-r--r--cpukit/libcsupport/src/statvfs.c52
-rw-r--r--cpukit/libcsupport/src/strlcat.c41
-rw-r--r--cpukit/libcsupport/src/strlcpy.c49
-rw-r--r--cpukit/libcsupport/src/sup_fs_get_start_loc.c48
-rw-r--r--cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c47
-rw-r--r--cpukit/libcsupport/src/sup_fs_is_separator.c30
-rw-r--r--cpukit/libcsupport/src/symlink.c42
-rw-r--r--cpukit/libcsupport/src/sync.c101
-rw-r--r--cpukit/libcsupport/src/tcdrain.c36
-rw-r--r--cpukit/libcsupport/src/tcflow.c44
-rw-r--r--cpukit/libcsupport/src/tcflush.c50
-rw-r--r--cpukit/libcsupport/src/tcgetattr.c36
-rw-r--r--cpukit/libcsupport/src/tcgetpgrp.c28
-rw-r--r--cpukit/libcsupport/src/tcsendbreak.c36
-rw-r--r--cpukit/libcsupport/src/tcsetattr.c51
-rw-r--r--cpukit/libcsupport/src/tcsetpgrp.c36
-rw-r--r--cpukit/libcsupport/src/termios.c1480
-rw-r--r--cpukit/libcsupport/src/termios_baud2index.c50
-rw-r--r--cpukit/libcsupport/src/termios_baud2num.c33
-rw-r--r--cpukit/libcsupport/src/termios_baudtable.c42
-rw-r--r--cpukit/libcsupport/src/termios_num2baud.c32
-rw-r--r--cpukit/libcsupport/src/termios_setinitialbaud.c33
-rw-r--r--cpukit/libcsupport/src/termiosinitialize.c54
-rw-r--r--cpukit/libcsupport/src/truncate.c43
-rw-r--r--cpukit/libcsupport/src/ttyname.c118
-rw-r--r--cpukit/libcsupport/src/umask.c33
-rw-r--r--cpukit/libcsupport/src/unlink.c103
-rw-r--r--cpukit/libcsupport/src/unmount.c162
-rw-r--r--cpukit/libcsupport/src/utime.c47
-rw-r--r--cpukit/libcsupport/src/utimes.c33
-rw-r--r--cpukit/libcsupport/src/utsname.c49
-rw-r--r--cpukit/libcsupport/src/vprintk.c191
-rw-r--r--cpukit/libcsupport/src/write.c53
-rw-r--r--cpukit/libcsupport/src/write_r.c40
-rw-r--r--cpukit/libcsupport/src/writev.c128
172 files changed, 12353 insertions, 0 deletions
diff --git a/cpukit/libcsupport/src/CASES b/cpukit/libcsupport/src/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/cpukit/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/cpukit/libcsupport/src/README b/cpukit/libcsupport/src/README
new file mode 100644
index 0000000000..ee7a90501e
--- /dev/null
+++ b/cpukit/libcsupport/src/README
@@ -0,0 +1,37 @@
+--
+-- $Id$
+--
+
+Overview of newlib support (newlib is from CYGNUS)
+ Each task can have its own libc state including:
+ open stdio files
+ strtok
+ multi precision arithmetic state
+ etc.
+
+ This is implemented by a reentrancy data structure for each task.
+
+ When a task is "started" (in RTEMS sense) the reentrancy structure
+ is allocated. Its address is stored in notepad[NOTEPAD_LAST].
+
+ When task is switched to, the value of global variable _impure_ptr
+ is changed to the value of the new tasks reentrancy structure.
+
+ When a task is deleted
+ atexit() processing (for that task) happens
+ task's stdio buffers are flushed
+
+ When exit(3) is called
+ calling task's atexit processing done
+ global libc state atexit processing done
+ (this will include any atexit routines installed by drivers)
+ executive is shutdown
+ causes a context switch back to bsp land
+
+
+NOTE:
+ libc extension are installed by bsp_libc_init()
+ iff we are using clock interrupts.
+ This hack is necessary to allow the tmtests to avoid
+ timing the extensions.
+
diff --git a/cpukit/libcsupport/src/TODO b/cpukit/libcsupport/src/TODO
new file mode 100644
index 0000000000..38cb012326
--- /dev/null
+++ b/cpukit/libcsupport/src/TODO
@@ -0,0 +1,14 @@
+#
+# $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.
+
++ Check the node allocation coment in the fchdir call.
++ Add an interface somewhere for this call. \ No newline at end of file
diff --git a/cpukit/libcsupport/src/__assert.c b/cpukit/libcsupport/src/__assert.c
new file mode 100644
index 0000000000..0e90b604c6
--- /dev/null
+++ b/cpukit/libcsupport/src/__assert.c
@@ -0,0 +1,52 @@
+/* __assert - small RTEMS Specific Implementation
+ *
+ * COPYRIGHT (c) 2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/bspIo.h>
+#include <rtems.h>
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE___ASSERT_FUNC)
+/*
+ * Newlib 1.16.0 added this method. Together these provide an
+ * RTEMS safe, low memory implementation.
+ */
+void __assert_func(
+ const char *file,
+ int line,
+ const char *func,
+ const char *failedexpr
+)
+{
+ printk("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
+ failedexpr,
+ file,
+ line,
+ (func) ? ", function: " : "",
+ (func) ? func : ""
+ );
+ rtems_fatal_error_occurred(0);
+}
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE___ASSERT)
+void __assert(
+ const char *file,
+ int line,
+ const char *failedexpr
+)
+{
+ __assert_func (file, line, NULL, failedexpr);
+}
+#endif
diff --git a/cpukit/libcsupport/src/__getpid.c b/cpukit/libcsupport/src/__getpid.c
new file mode 100644
index 0000000000..85a4c0b013
--- /dev/null
+++ b/cpukit/libcsupport/src/__getpid.c
@@ -0,0 +1,17 @@
+/*
+ * Some C Libraries reference this routine since they think getpid is
+ * a real system call.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+pid_t __getpid(void)
+{
+ return getpid();
+}
diff --git a/cpukit/libcsupport/src/__gettod.c b/cpukit/libcsupport/src/__gettod.c
new file mode 100644
index 0000000000..05db4ab9d0
--- /dev/null
+++ b/cpukit/libcsupport/src/__gettod.c
@@ -0,0 +1,86 @@
+/*
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#if defined(RTEMS_NEWLIB)
+#include <sys/time.h>
+#include <errno.h>
+#include <rtems.h>
+#include <rtems/seterr.h>
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_GETTIMEOFDAY)
+/*
+ * NOTE: The solaris gettimeofday does not have a second parameter.
+ */
+int gettimeofday(
+ struct timeval *tp,
+ void * __tz __attribute__((unused))
+)
+{
+ /* struct timezone* tzp = (struct timezone*) __tz; */
+ if ( !tp )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * POSIX does not seem to allow for not having a TOD so we just
+ * grab the time of day.
+ */
+ _TOD_Get_timeval( tp );
+
+ /*
+ * Timezone information ignored by the OS proper. Per email
+ * with Eric Norum, this is how GNU/Linux, Solaris, and MacOS X
+ * do it. This puts us in good company.
+ */
+
+ return 0;
+}
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__GETTIMEOFDAY_R)
+
+#include <sys/reent.h>
+
+/*
+ * "Reentrant" version
+ */
+int _gettimeofday_r(
+ struct _reent *ignored_reentrancy_stuff __attribute__((unused)),
+ struct timeval *tp,
+ struct timezone *tzp
+)
+{
+ return gettimeofday( tp, tzp );
+}
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__GETTIMEOFDAY)
+/*
+ * "System call" version
+ */
+
+int _gettimeofday(
+ struct timeval *tp,
+ struct timezone *tzp
+)
+{
+ return gettimeofday( tp, tzp );
+}
+#endif
+
+#endif /* defined(RTEMS_NEWLIB) */
diff --git a/cpukit/libcsupport/src/__times.c b/cpukit/libcsupport/src/__times.c
new file mode 100644
index 0000000000..2de529275e
--- /dev/null
+++ b/cpukit/libcsupport/src/__times.c
@@ -0,0 +1,114 @@
+/*
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <sys/times.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <rtems/seterr.h>
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ #include <rtems/score/timestamp.h>
+#endif
+
+clock_t _times(
+ struct tms *ptms
+)
+{
+ rtems_interval ticks;
+
+ if ( !ptms )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * This call does not depend on TOD being initialized and can't fail.
+ */
+
+ ticks = rtems_clock_get_ticks_since_boot();
+
+ /*
+ * RTEMS technically has no notion of system versus user time
+ * since there is no separation of OS from application tasks.
+ * But we can at least make a distinction between the number
+ * of ticks since boot and the number of ticks executed by this
+ * this thread.
+ */
+
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ {
+ Timestamp_Control per_tick;
+ uint32_t ticks;
+ uint32_t fractional_ticks;
+
+ _Timestamp_Set(
+ &per_tick,
+ rtems_configuration_get_microseconds_per_tick() /
+ TOD_MICROSECONDS_PER_SECOND,
+ (rtems_configuration_get_nanoseconds_per_tick() %
+ TOD_NANOSECONDS_PER_SECOND)
+ );
+
+ _Timestamp_Divide(
+ &_Thread_Executing->cpu_time_used,
+ &per_tick,
+ &ticks,
+ &fractional_ticks
+ );
+ ptms->tms_utime = ticks;
+ }
+ #else
+ ptms->tms_utime = _Thread_Executing->cpu_time_used;
+ #endif
+ ptms->tms_stime = ticks;
+ ptms->tms_cutime = 0;
+ ptms->tms_cstime = 0;
+
+ return ticks;
+}
+
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
+clock_t times(
+ struct tms *ptms
+)
+{
+ 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 __attribute__((unused)),
+ struct tms *ptms
+)
+{
+ return _times( ptms );
+}
+#endif
diff --git a/cpukit/libcsupport/src/__usrenv.c b/cpukit/libcsupport/src/__usrenv.c
new file mode 100644
index 0000000000..0b3469fa1a
--- /dev/null
+++ b/cpukit/libcsupport/src/__usrenv.c
@@ -0,0 +1,27 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+/*
+ * Global information for POSIX Process Environment Support
+ */
+
+rtems_user_env_t rtems_global_user_env;
+rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env;
+
+
diff --git a/cpukit/libcsupport/src/_calloc_r.c b/cpukit/libcsupport/src/_calloc_r.c
new file mode 100644
index 0000000000..1b515d2464
--- /dev/null
+++ b/cpukit/libcsupport/src/_calloc_r.c
@@ -0,0 +1,30 @@
+/*
+ * _calloc_r Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__CALLOC_R)
+#include <sys/reent.h>
+#include <stdlib.h>
+
+void *_calloc_r(
+ struct _reent *ignored __attribute__((unused)),
+ size_t elements,
+ size_t size
+)
+{
+ return calloc( elements, size );
+}
+#endif
diff --git a/cpukit/libcsupport/src/_free_r.c b/cpukit/libcsupport/src/_free_r.c
new file mode 100644
index 0000000000..9b3eb5c285
--- /dev/null
+++ b/cpukit/libcsupport/src/_free_r.c
@@ -0,0 +1,29 @@
+/*
+ * _free_r Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__FREE_R)
+#include <sys/reent.h>
+#include <stdlib.h>
+
+void _free_r(
+ struct _reent *ignored __attribute__((unused)),
+ void *ptr
+)
+{
+ free( ptr );
+}
+#endif
diff --git a/cpukit/libcsupport/src/_malloc_r.c b/cpukit/libcsupport/src/_malloc_r.c
new file mode 100644
index 0000000000..9a30097324
--- /dev/null
+++ b/cpukit/libcsupport/src/_malloc_r.c
@@ -0,0 +1,29 @@
+/*
+ * _malloc_r Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__MALLOC_R)
+#include <sys/reent.h>
+#include <stdlib.h>
+
+void *_malloc_r(
+ struct _reent *ignored __attribute__((unused)),
+ size_t size
+)
+{
+ return malloc( size );
+}
+#endif
diff --git a/cpukit/libcsupport/src/_realloc_r.c b/cpukit/libcsupport/src/_realloc_r.c
new file mode 100644
index 0000000000..78c9faf351
--- /dev/null
+++ b/cpukit/libcsupport/src/_realloc_r.c
@@ -0,0 +1,30 @@
+/*
+ * _realloc_r Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__REALLOC_R)
+#include <sys/reent.h>
+#include <stdlib.h>
+
+void *_realloc_r(
+ struct _reent *ignored __attribute__((unused)),
+ void *ptr,
+ size_t size
+)
+{
+ return realloc( ptr, size );
+}
+#endif
diff --git a/cpukit/libcsupport/src/_rename_r.c b/cpukit/libcsupport/src/_rename_r.c
new file mode 100644
index 0000000000..51010df28e
--- /dev/null
+++ b/cpukit/libcsupport/src/_rename_r.c
@@ -0,0 +1,113 @@
+/*
+ * _rename_r() - POSIX 1003.1b - 5.3.4 - Rename a file
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__RENAME_R)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int _rename_r(
+ struct _reent *ptr __attribute__((unused)),
+ const char *old,
+ const char *new
+)
+{
+ int old_parent_pathlen;
+ rtems_filesystem_location_info_t old_loc;
+ rtems_filesystem_location_info_t old_parent_loc;
+ rtems_filesystem_location_info_t new_parent_loc;
+ int i;
+ int result;
+ const char *name;
+ bool free_old_parentloc = false;
+
+ /*
+ * Get the parent node of the old path to be renamed. Find the parent path.
+ */
+
+ old_parent_pathlen = rtems_filesystem_dirname ( old );
+
+ if ( old_parent_pathlen == 0 )
+ rtems_filesystem_get_start_loc( old, &i, &old_parent_loc );
+ else {
+ result = rtems_filesystem_evaluate_path( old, old_parent_pathlen,
+ RTEMS_LIBIO_PERMS_WRITE,
+ &old_parent_loc,
+ false );
+ if ( result != 0 )
+ return -1;
+
+ free_old_parentloc = true;
+ }
+
+ /*
+ * Start from the parent to find the node that should be under it.
+ */
+
+ old_loc = old_parent_loc;
+ name = old + old_parent_pathlen;
+ name += rtems_filesystem_prefix_separators( name, strlen( name ) );
+
+ result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
+ 0, &old_loc, false );
+ if ( result != 0 ) {
+ if ( free_old_parentloc )
+ rtems_filesystem_freenode( &old_parent_loc );
+ return -1;
+ }
+
+ /*
+ * Get the parent of the new node we are renaming to.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &new_parent_loc );
+
+ result = (*new_parent_loc.ops->evalformake_h)( &new[i], &new_parent_loc, &name );
+ if ( result != 0 ) {
+ rtems_filesystem_freenode( &new_parent_loc );
+ if ( free_old_parentloc )
+ rtems_filesystem_freenode( &old_parent_loc );
+ rtems_filesystem_freenode( &old_loc );
+ return -1;
+ }
+
+ /*
+ * Check to see if the caller is trying to rename across file system
+ * boundaries.
+ */
+
+ if ( old_parent_loc.mt_entry != new_parent_loc.mt_entry ) {
+ rtems_filesystem_freenode( &new_parent_loc );
+ if ( free_old_parentloc )
+ rtems_filesystem_freenode( &old_parent_loc );
+ rtems_filesystem_freenode( &old_loc );
+ rtems_set_errno_and_return_minus_one( EXDEV );
+ }
+
+ result = (*new_parent_loc.ops->rename_h)( &old_parent_loc, &old_loc, &new_parent_loc, name );
+
+ rtems_filesystem_freenode( &new_parent_loc );
+ if ( free_old_parentloc )
+ rtems_filesystem_freenode( &old_parent_loc );
+ rtems_filesystem_freenode( &old_loc );
+
+ return result;
+}
+#endif
diff --git a/cpukit/libcsupport/src/access.c b/cpukit/libcsupport/src/access.c
new file mode 100644
index 0000000000..7365d6db7d
--- /dev/null
+++ b/cpukit/libcsupport/src/access.c
@@ -0,0 +1,48 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/assoclocalbyname.c b/cpukit/libcsupport/src/assoclocalbyname.c
new file mode 100644
index 0000000000..28856afc46
--- /dev/null
+++ b/cpukit/libcsupport/src/assoclocalbyname.c
@@ -0,0 +1,31 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+uint32_t rtems_assoc_local_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+)
+{
+ const rtems_assoc_t *nap;
+
+ nap = rtems_assoc_ptr_by_name(ap, name);
+ if (nap)
+ return nap->local_value;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/assoclocalbyremote.c b/cpukit/libcsupport/src/assoclocalbyremote.c
new file mode 100644
index 0000000000..545f31b6a8
--- /dev/null
+++ b/cpukit/libcsupport/src/assoclocalbyremote.c
@@ -0,0 +1,31 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+uint32_t rtems_assoc_local_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+)
+{
+ const rtems_assoc_t *nap;
+
+ nap = rtems_assoc_ptr_by_remote(ap, remote_value);
+ if (nap)
+ return nap->local_value;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/assoclocalbyremotebitfield.c b/cpukit/libcsupport/src/assoclocalbyremotebitfield.c
new file mode 100644
index 0000000000..177ca62b49
--- /dev/null
+++ b/cpukit/libcsupport/src/assoclocalbyremotebitfield.c
@@ -0,0 +1,34 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+
+uint32_t rtems_assoc_local_by_remote_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+)
+{
+ uint32_t b;
+ uint32_t local_value = 0;
+
+ for (b = 1; b; b <<= 1) {
+ if (b & remote_value)
+ local_value |= rtems_assoc_local_by_remote(ap, b);
+ }
+
+ return local_value;
+}
diff --git a/cpukit/libcsupport/src/assocnamebad.c b/cpukit/libcsupport/src/assocnamebad.c
new file mode 100644
index 0000000000..f61f4e844d
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebad.c
@@ -0,0 +1,40 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <inttypes.h>
+#include <stdio.h> /* sprintf */
+
+/*
+ * what to return if a value is not found
+ * this is not reentrant, but it really shouldn't be invoked anyway
+ */
+
+const char *
+rtems_assoc_name_bad(
+#ifdef RTEMS_DEBUG
+ uint32_t bad_value
+#else
+ uint32_t bad_value __attribute((unused))
+#endif
+)
+{
+#ifdef RTEMS_DEBUG
+ static char bad_buffer[32];
+
+ sprintf(bad_buffer, "< %" PRId32 "[0x%" PRIx32 " ] >", bad_value, bad_value);
+#else
+ static char bad_buffer[40] = "<assocnamebad.c: : BAD NAME>";
+#endif
+ return bad_buffer;
+}
diff --git a/cpukit/libcsupport/src/assocnamebylocal.c b/cpukit/libcsupport/src/assocnamebylocal.c
new file mode 100644
index 0000000000..3ba0b8c083
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebylocal.c
@@ -0,0 +1,31 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+const char *rtems_assoc_name_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+)
+{
+ const rtems_assoc_t *nap;
+
+ nap = rtems_assoc_ptr_by_local(ap, local_value);
+ if (nap)
+ return nap->name;
+
+ return rtems_assoc_name_bad(local_value);
+}
diff --git a/cpukit/libcsupport/src/assocnamebylocalbitfield.c b/cpukit/libcsupport/src/assocnamebylocalbitfield.c
new file mode 100644
index 0000000000..c9d1fa1256
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebylocalbitfield.c
@@ -0,0 +1,38 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+char *rtems_assoc_name_by_local_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t value,
+ char *buffer
+)
+{
+ uint32_t b;
+
+ *buffer = 0;
+
+ for (b = 1; b; b <<= 1) {
+ if (b & value) {
+ if (*buffer)
+ strcat(buffer, " ");
+ strcat(buffer, rtems_assoc_name_by_local(ap, b));
+ }
+ }
+
+ return buffer;
+}
diff --git a/cpukit/libcsupport/src/assocnamebyremote.c b/cpukit/libcsupport/src/assocnamebyremote.c
new file mode 100644
index 0000000000..281022c7bf
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebyremote.c
@@ -0,0 +1,33 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+
+const char *rtems_assoc_name_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+)
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_remote(ap, remote_value);
+
+ if (nap)
+ return nap->name;
+
+ return rtems_assoc_name_bad(remote_value);
+}
+
diff --git a/cpukit/libcsupport/src/assocnamebyremotebitfield.c b/cpukit/libcsupport/src/assocnamebyremotebitfield.c
new file mode 100644
index 0000000000..1293393e1e
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebyremotebitfield.c
@@ -0,0 +1,39 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+
+char *rtems_assoc_name_by_remote_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t value,
+ char *buffer
+)
+{
+ uint32_t b;
+
+ *buffer = 0;
+
+ for (b = 1; b; b <<= 1) {
+ if (b & value) {
+ if (*buffer)
+ strcat(buffer, " ");
+ strcat(buffer, rtems_assoc_name_by_remote(ap, b));
+ }
+ }
+
+ return buffer;
+}
diff --git a/cpukit/libcsupport/src/assocptrbylocal.c b/cpukit/libcsupport/src/assocptrbylocal.c
new file mode 100644
index 0000000000..cbf26b1bcb
--- /dev/null
+++ b/cpukit/libcsupport/src/assocptrbylocal.c
@@ -0,0 +1,34 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+const rtems_assoc_t *rtems_assoc_ptr_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+)
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (ap->local_value == local_value)
+ return ap;
+
+ return default_ap;
+}
diff --git a/cpukit/libcsupport/src/assocptrbyname.c b/cpukit/libcsupport/src/assocptrbyname.c
new file mode 100644
index 0000000000..457f57e434
--- /dev/null
+++ b/cpukit/libcsupport/src/assocptrbyname.c
@@ -0,0 +1,35 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+
+const rtems_assoc_t *rtems_assoc_ptr_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+)
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (strcmp(ap->name, name) == 0)
+ return ap;
+
+ return default_ap;
+}
diff --git a/cpukit/libcsupport/src/assocptrbyremote.c b/cpukit/libcsupport/src/assocptrbyremote.c
new file mode 100644
index 0000000000..4879c2d397
--- /dev/null
+++ b/cpukit/libcsupport/src/assocptrbyremote.c
@@ -0,0 +1,34 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+const rtems_assoc_t *rtems_assoc_ptr_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+)
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (ap->remote_value == remote_value)
+ return ap;
+
+ return default_ap;
+}
diff --git a/cpukit/libcsupport/src/assocremotebylocal.c b/cpukit/libcsupport/src/assocremotebylocal.c
new file mode 100644
index 0000000000..23bbcc74fa
--- /dev/null
+++ b/cpukit/libcsupport/src/assocremotebylocal.c
@@ -0,0 +1,31 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+uint32_t rtems_assoc_remote_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+)
+{
+ const rtems_assoc_t *nap;
+
+ nap = rtems_assoc_ptr_by_local(ap, local_value);
+ if (nap)
+ return nap->remote_value;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/assocremotebylocalbitfield.c b/cpukit/libcsupport/src/assocremotebylocalbitfield.c
new file mode 100644
index 0000000000..3d28345847
--- /dev/null
+++ b/cpukit/libcsupport/src/assocremotebylocalbitfield.c
@@ -0,0 +1,33 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+
+uint32_t rtems_assoc_remote_by_local_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+)
+{
+ uint32_t b;
+ uint32_t remote_value = 0;
+
+ for (b = 1; b; b <<= 1)
+ if (b & local_value)
+ remote_value |= rtems_assoc_remote_by_local(ap, b);
+
+ return remote_value;
+}
diff --git a/cpukit/libcsupport/src/assocremotebyname.c b/cpukit/libcsupport/src/assocremotebyname.c
new file mode 100644
index 0000000000..923c8d28ba
--- /dev/null
+++ b/cpukit/libcsupport/src/assocremotebyname.c
@@ -0,0 +1,31 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define INSIDE_ASSOC
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+uint32_t rtems_assoc_remote_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+)
+{
+ const rtems_assoc_t *nap;
+
+ nap = rtems_assoc_ptr_by_name(ap, name);
+ if (nap)
+ return nap->remote_value;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c
new file mode 100644
index 0000000000..b5681eda63
--- /dev/null
+++ b/cpukit/libcsupport/src/base_fs.c
@@ -0,0 +1,114 @@
+/*
+ * Base file system initialization
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+/*
+ * Default mode for created files.
+ */
+
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system. This is specified
+ * by the structure rtems_filesystem_mount_table. The usual
+ * configuration is a single instantiation of the IMFS or miniIMFS with
+ * a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+ int status;
+ const rtems_filesystem_mount_table_t *mt;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = 022;
+
+ /*
+ * mount the first filesystem.
+ */
+ if ( rtems_filesystem_mount_table_size == 0 )
+ rtems_fatal_error_occurred( 0xABCD0001 );
+
+ mt = &rtems_filesystem_mount_table[0];
+
+ status = mount( mt->device, mt->mount_point, mt->type, mt->fsoptions, NULL );
+ if ( status == -1 )
+ rtems_fatal_error_occurred( 0xABCD0002 );
+
+ rtems_filesystem_link_counts = 0;
+
+ /* setup the 'current' and 'root' directories
+ *
+ * NOTE: cloning the pathlocs is not strictly
+ * necessary. Since we implicitely let
+ * all threads that don't call
+ * libio_set_private_env() share the same
+ * (initial) 'root' and 'current' locs,
+ * we (also implicitely) assume that the
+ * root filesystem doesn't care about
+ * reference counts.
+ * I just inserted the code snippet below
+ * to remind everybody of the fact by
+ * making it more explicit...
+ * Ideally, every thread would have to
+ * call either share_private_env() or
+ * set_private_env() - but then: that's
+ * gonna hit performance.
+ *
+ * Till Straumann, 10/25/2002
+ */
+ /* Clone the root pathloc */
+ rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
+ rtems_filesystem_root = loc;
+ /* One more clone for the current node */
+ rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
+ rtems_filesystem_current = loc;
+
+ /* Note: the global_env's refcnt doesn't matter
+ * as the global env is never released
+ */
+
+
+ /*
+ * 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). It is actually
+ * created that way by the IMFS.
+ */
+
+ status = mkdir( "/dev", 0777);
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+
+ /*
+ * You can't mount another filesystem properly until the mount point
+ * it will be mounted onto is created. Moreover, if it is going to
+ * use a device, then it is REALLY unfair to attempt this
+ * before device drivers are initialized. So we return via a base
+ * filesystem image and nothing auto-mounted at this point.
+ */
+}
diff --git a/cpukit/libcsupport/src/calloc.c b/cpukit/libcsupport/src/calloc.c
new file mode 100644
index 0000000000..859b4c2213
--- /dev/null
+++ b/cpukit/libcsupport/src/calloc.c
@@ -0,0 +1,41 @@
+/*
+ * calloc()
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_CALLOC)
+#include "malloc_p.h"
+#include <stdlib.h>
+
+void *calloc(
+ size_t nelem,
+ size_t elsize
+)
+{
+ register char *cptr;
+ size_t length;
+
+ MSBUMP(calloc_calls, 1);
+
+ length = nelem * elsize;
+ cptr = malloc( length );
+ if ( cptr )
+ memset( cptr, '\0', length );
+
+ MSBUMP(malloc_calls, (uint32_t) -1); /* subtract off the malloc */
+
+ return cptr;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfgetispeed.c b/cpukit/libcsupport/src/cfgetispeed.c
new file mode 100644
index 0000000000..225c7311cc
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetispeed.c
@@ -0,0 +1,32 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/cfgetospeed.c b/cpukit/libcsupport/src/cfgetospeed.c
new file mode 100644
index 0000000000..e239e54758
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetospeed.c
@@ -0,0 +1,32 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/cfsetispeed.c b/cpukit/libcsupport/src/cfsetispeed.c
new file mode 100644
index 0000000000..383762bee1
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetispeed.c
@@ -0,0 +1,40 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfsetospeed.c b/cpukit/libcsupport/src/cfsetospeed.c
new file mode 100644
index 0000000000..0badcbbdc7
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetospeed.c
@@ -0,0 +1,40 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c
new file mode 100644
index 0000000000..c9d05f0bef
--- /dev/null
+++ b/cpukit/libcsupport/src/chdir.c
@@ -0,0 +1,57 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ if ( !pathname )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Get the node where we wish to go.
+ */
+ result = rtems_filesystem_evaluate_path(
+ pathname, strlen( pathname ), RTEMS_LIBIO_PERMS_SEARCH, &loc, true );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+ rtems_filesystem_freenode( &rtems_filesystem_current );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c
new file mode 100644
index 0000000000..d1d9ae0f5f
--- /dev/null
+++ b/cpukit/libcsupport/src/chmod.c
@@ -0,0 +1,46 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ status = rtems_filesystem_evaluate_path( path, strlen( path ), 0, &loc, true );
+ if ( status != 0 )
+ return -1;
+
+ result = (*loc.handlers->fchmod_h)( &loc, mode );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c
new file mode 100644
index 0000000000..3cab985cad
--- /dev/null
+++ b/cpukit/libcsupport/src/chown.c
@@ -0,0 +1,54 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int _chown_helper(
+ const char *path,
+ uid_t owner,
+ gid_t group,
+ int follow_link
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &loc, follow_link ) )
+ return -1;
+
+ result = (*loc.ops->chown_h)( &loc, owner, group );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ return _chown_helper( path, owner, group, true );
+}
diff --git a/cpukit/libcsupport/src/chroot.c b/cpukit/libcsupport/src/chroot.c
new file mode 100644
index 0000000000..ccda4d6d7a
--- /dev/null
+++ b/cpukit/libcsupport/src/chroot.c
@@ -0,0 +1,55 @@
+/*
+ * chroot() - Change Root Directory
+ * Author: fernando.ruiz@ctv.es
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chroot(
+ const char *pathname
+)
+{
+ int result;
+ rtems_filesystem_location_info_t loc;
+
+ /* an automatic call to new private env the first time */
+ if (rtems_current_user_env == &rtems_global_user_env) {
+ rtems_libio_set_private_env(); /* try to set a new private env*/
+ if (rtems_current_user_env == &rtems_global_user_env) /* not ok */
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = chdir(pathname);
+ if (result) {
+ rtems_set_errno_and_return_minus_one( errno );
+ }
+
+ /* clone the new root location */
+ if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
+ /* our cwd has changed, though - but there is no easy way of return :-( */
+ rtems_set_errno_and_return_minus_one( errno );
+ }
+ rtems_filesystem_freenode(&rtems_filesystem_root);
+ rtems_filesystem_root = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c
new file mode 100644
index 0000000000..726bca11d9
--- /dev/null
+++ b/cpukit/libcsupport/src/close.c
@@ -0,0 +1,57 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+
+ rtems_libio_check_fd(fd);
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_is_open(iop);
+
+ rc = RTEMS_SUCCESSFUL;
+ rc = (*iop->pathinfo.handlers->close_h)( iop );
+
+ rtems_filesystem_freenode( &iop->pathinfo );
+ rtems_libio_free( iop );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__CLOSE_R)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/cpukit/libcsupport/src/ctermid.c b/cpukit/libcsupport/src/ctermid.c
new file mode 100644
index 0000000000..37b2f9cfc0
--- /dev/null
+++ b/cpukit/libcsupport/src/ctermid.c
@@ -0,0 +1,42 @@
+/*
+ * ctermid() - POSIX 1003.1b 4.7.1 - Generate Terminal Pathname
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <stdio.h>
+#include <string.h>
+
+static char *ctermid_name = "/dev/console";
+
+char *ctermid(
+ char *s
+)
+{
+ if ( !s )
+ return ctermid_name;
+
+ /*
+ * We have no way of knowing the length of the user provided buffer.
+ * It may not be large enough but there is no way to know that. :(
+ * So this is a potential buffer owerrun that we can do nothing about.
+ */
+ strcpy( s, ctermid_name );
+ return s;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/dup.c b/cpukit/libcsupport/src/dup.c
new file mode 100644
index 0000000000..684d72d92f
--- /dev/null
+++ b/cpukit/libcsupport/src/dup.c
@@ -0,0 +1,26 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/cpukit/libcsupport/src/dup2.c b/cpukit/libcsupport/src/dup2.c
new file mode 100644
index 0000000000..15998f797c
--- /dev/null
+++ b/cpukit/libcsupport/src/dup2.c
@@ -0,0 +1,52 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <rtems/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/cpukit/libcsupport/src/envlock.c b/cpukit/libcsupport/src/envlock.c
new file mode 100644
index 0000000000..9594e0abe3
--- /dev/null
+++ b/cpukit/libcsupport/src/envlock.c
@@ -0,0 +1,108 @@
+/*
+ * Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
+ *
+ * $Id$
+ */
+
+/* provide locking for the global environment 'environ' */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <sys/reent.h>
+
+#include <assert.h>
+
+/*
+ * NOTES:
+ * - although it looks like a classical multiple-readers / single writer (MRSW)
+ * locking problem, we still use a single lock for the following reasons:
+ * 1) newlib has no provision / hook for calling different locking routines
+ * from setenv/putenv and getenv, respectively.
+ * 2) MRSW involves calling several semaphore-primitives, even in the most
+ * likely case of a first-reader's access. This probably takes more CPU
+ * time than just waiting until another reader is done; environment
+ * access is fast.
+ * - the lock implementation must allow nesting (same thread may call
+ * lock-lock-unlock-unlock).
+ * - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
+ * out leaving the lock held :-(
+ *
+ * Used by the following functions:
+ * findenv_r(), setenv_r(), and unsetenv_r() which are called by
+ * getenv(), getenv_r(), setenv(), and unsetenv().
+ *
+ */
+
+#if defined(ENVLOCK_DEDIDCATED_MUTEX)
+static rtems_id envLock=0;
+
+static void
+__rtems_envlock_init(void)
+{
+ extern char **environ;
+ rtems_status_code rc;
+
+ if (envLock) /* already initialized */
+ return;
+
+ assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
+
+ rc = rtems_semaphore_create(
+ rtems_build_name('E','N','V','S'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+ 0,
+ &envLock);
+ if (RTEMS_SUCCESSFUL!=rc)
+ rtems_fatal_error_occurred(rc);
+}
+
+void
+__env_lock(struct _reent *r)
+{
+ /* Do lazy init */
+ if (!envLock)
+ __rtems_envlock_init();
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+
+ if (_Thread_Executing)
+ rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+void
+__env_unlock(struct _reent *r)
+{
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+ if (_Thread_Executing)
+ rtems_semaphore_release(envLock);
+}
+#else
+
+/*
+ * Reuse the libio mutex -- it is always initialized before we
+ * could possibly run.
+ */
+
+#include <rtems/libio_.h>
+
+void
+__env_lock(struct _reent *r __attribute__((unused)))
+{
+ rtems_libio_lock();
+}
+
+void
+__env_unlock(struct _reent *r __attribute__((unused)))
+{
+ rtems_libio_unlock();
+}
+#endif
diff --git a/cpukit/libcsupport/src/error.c b/cpukit/libcsupport/src/error.c
new file mode 100644
index 0000000000..074707c54c
--- /dev/null
+++ b/cpukit/libcsupport/src/error.c
@@ -0,0 +1,209 @@
+/*
+ * report errors and panics to RTEMS' stderr.
+ * Currently just used by RTEMS monitor.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * These routines provide general purpose error reporting.
+ * rtems_error reports an error to stderr and allows use of
+ * printf style formatting. A newline is appended to all messages.
+ *
+ * error_flag can be specified as any of the following:
+ *
+ * RTEMS_ERROR_ERRNO -- include errno text in output
+ * RTEMS_ERROR_PANIC -- halts local system after output
+ * RTEMS_ERROR_ABORT -- abort after output
+ *
+ * It can also include a rtems_status value which can be OR'd
+ * with the above flags. *
+ *
+ * EXAMPLE
+ * #include <rtems.h>
+ * #include <rtems/error.h>
+ * rtems_error(0, "stray interrupt %d", intr);
+ *
+ * EXAMPLE
+ * if ((status = rtems_task_create(...)) != RTEMS_SUCCCESSFUL)
+ * {
+ * rtems_error(status | RTEMS_ERROR_ABORT,
+ * "could not create task");
+ * }
+ *
+ * EXAMPLE
+ * if ((fd = open(pathname, O_RDNLY)) < 0)
+ * {
+ * rtems_error(RTEMS_ERROR_ERRNO, "open of '%s' failed", pathname);
+ * goto failed;
+ * }
+ */
+
+/* This is always defined on RTEMS Scheduler Simulator and thus
+ * we get a redefined warning if this is not present.
+ */
+#ifndef __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+ #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#endif
+#include <rtems.h>
+
+#include <rtems/error.h>
+#include <rtems/assoc.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h> /* _exit() */
+
+int rtems_panic_in_progress;
+
+const rtems_assoc_t rtems_status_assoc[] = {
+ { "successful completion", RTEMS_SUCCESSFUL, 0 },
+ { "returned from a thread", RTEMS_TASK_EXITTED, 0 },
+ { "multiprocessing not configured", RTEMS_MP_NOT_CONFIGURED, 0 },
+ { "invalid object name", RTEMS_INVALID_NAME, 0 },
+ { "invalid object id", RTEMS_INVALID_ID, 0 },
+ { "too many", RTEMS_TOO_MANY, 0 },
+ { "timed out waiting", RTEMS_TIMEOUT, 0 },
+ { "object deleted while waiting", RTEMS_OBJECT_WAS_DELETED, 0 },
+ { "specified size was invalid", RTEMS_INVALID_SIZE, 0 },
+ { "address specified is invalid", RTEMS_INVALID_ADDRESS, 0 },
+ { "number was invalid", RTEMS_INVALID_NUMBER, 0 },
+ { "item has not been initialized", RTEMS_NOT_DEFINED, 0 },
+ { "resources still outstanding", RTEMS_RESOURCE_IN_USE, 0 },
+ { "request not satisfied", RTEMS_UNSATISFIED, 0 },
+ { "thread is in wrong state", RTEMS_INCORRECT_STATE, 0 },
+ { "thread already in state", RTEMS_ALREADY_SUSPENDED, 0 },
+ { "illegal on calling thread", RTEMS_ILLEGAL_ON_SELF, 0 },
+ { "illegal for remote object", RTEMS_ILLEGAL_ON_REMOTE_OBJECT, 0 },
+ { "called from wrong environment", RTEMS_CALLED_FROM_ISR, 0 },
+ { "invalid thread priority", RTEMS_INVALID_PRIORITY, 0 },
+ { "invalid date/time", RTEMS_INVALID_CLOCK, 0 },
+ { "invalid node id", RTEMS_INVALID_NODE, 0 },
+ { "directive not configured", RTEMS_NOT_CONFIGURED, 0 },
+ { "not owner of resource", RTEMS_NOT_OWNER_OF_RESOURCE , 0 },
+ { "directive not implemented", RTEMS_NOT_IMPLEMENTED, 0 },
+ { "RTEMS inconsistency detected", RTEMS_INTERNAL_ERROR, 0 },
+ { "could not get enough memory", RTEMS_NO_MEMORY, 0 },
+ { "driver IO error", RTEMS_IO_ERROR, 0 },
+ { "internal multiprocessing only", THREAD_STATUS_PROXY_BLOCKING, 0 },
+ { 0, 0, 0 },
+};
+
+
+const char *rtems_status_text(
+ rtems_status_code status
+)
+{
+ return rtems_assoc_name_by_local(rtems_status_assoc, status);
+}
+
+
+static int rtems_verror(
+ rtems_error_code_t error_flag,
+ const char *printf_format,
+ va_list arglist
+)
+{
+ int local_errno = 0;
+ int chars_written = 0;
+ rtems_status_code status;
+
+ if (error_flag & RTEMS_ERROR_PANIC) {
+ if (rtems_panic_in_progress++)
+ _Thread_Disable_dispatch(); /* disable task switches */
+
+ /* don't aggravate things */
+ if (rtems_panic_in_progress > 2)
+ return 0;
+ }
+
+ (void) fflush(stdout); /* in case stdout/stderr same */
+
+ status = error_flag & ~RTEMS_ERROR_MASK;
+ if (error_flag & RTEMS_ERROR_ERRNO) /* include errno? */
+ local_errno = errno;
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ if (_System_state_Is_multiprocessing)
+ fprintf(stderr, "[%" PRIu32 "] ", _Configuration_MP_table->node);
+ #endif
+
+ chars_written += vfprintf(stderr, printf_format, arglist);
+
+ if (status)
+ chars_written +=
+ fprintf(stderr, " (status: %s)", rtems_status_text(status));
+
+ if (local_errno) {
+ if ((local_errno > 0) && *strerror(local_errno))
+ chars_written += fprintf(stderr, " (errno: %s)", strerror(local_errno));
+ else
+ chars_written += fprintf(stderr, " (unknown errno=%d)", local_errno);
+ }
+
+ chars_written += fprintf(stderr, "\n");
+
+ (void) fflush(stderr);
+
+ return chars_written;
+}
+
+
+/*
+ * Report an error.
+ * error_flag is as above; printf_format is a normal
+ * printf(3) format string, with its concommitant arguments.
+ *
+ * Returns the number of characters written.
+ */
+
+int rtems_error(
+ rtems_error_code_t error_flag,
+ const char *printf_format,
+ ...
+)
+{
+ va_list arglist;
+ int chars_written;
+
+ va_start(arglist, printf_format);
+ chars_written = rtems_verror(error_flag, printf_format, arglist);
+ va_end(arglist);
+
+ if (error_flag & RTEMS_ERROR_PANIC) {
+ rtems_error(0, "fatal error, exiting");
+ _exit(errno);
+ }
+ if (error_flag & RTEMS_ERROR_ABORT) {
+ rtems_error(0, "fatal error, aborting");
+ abort();
+ }
+
+ return chars_written;
+}
+
+/*
+ * rtems_panic is shorthand for rtems_error(RTEMS_ERROR_PANIC, ...)
+ */
+
+void rtems_panic(
+ const char *printf_format,
+ ...
+)
+{
+ va_list arglist;
+
+ va_start(arglist, printf_format);
+ (void) rtems_verror(RTEMS_ERROR_PANIC, printf_format, arglist);
+ va_end(arglist);
+
+ rtems_error(0, "fatal error, exiting");
+ _exit(errno);
+}
diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c
new file mode 100644
index 0000000000..5a9118d3e1
--- /dev/null
+++ b/cpukit/libcsupport/src/eval.c
@@ -0,0 +1,151 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int rtems_filesystem_evaluate_relative_path(
+ const char *pathname,
+ size_t pathnamelen,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ #if defined(RTEMS_DEBUG)
+ /*
+ * Verify Input parameters that should never be bad unless someone
+ * is implementing a new filesystem and has bugs.
+ */
+ if ( !pathname )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ rtems_set_errno_and_return_minus_one( EIO );
+ #endif
+
+ result = (*pathloc->ops->evalpath_h)( pathname, pathnamelen, flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( (result == 0) && follow_link ) {
+
+ type = (*pathloc->ops->node_type_h)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ /* what to do with the valid node pathloc points to
+ * if eval_link_h fails?
+ * Let the FS implementation deal with this case. It
+ * should probably free pathloc in either case:
+ * - if the link evaluation fails, it must free the
+ * original (valid) pathloc because we are going
+ * to return -1 and hence the FS generics won't
+ * cleanup pathloc.
+ * - if the link evaluation is successful, the updated
+ * pathloc will be passed up (and eventually released).
+ * Hence, the (valid) originial node that we submit to
+ * eval_link_h() should be released by the handler.
+ */
+
+ result = (*pathloc->ops->eval_link_h)( pathloc, flags );
+ }
+ }
+
+ return result;
+}
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ size_t pathnamelen,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i = 0;
+
+ #if defined(RTEMS_DEBUG)
+ /*
+ * Verify Input parameters that should never be bad unless someone
+ * is implementing a new filesystem and has bugs.
+ */
+ if ( !pathname )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ rtems_set_errno_and_return_minus_one( EIO );
+ #endif
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ /*
+ * We evaluation the path relative to the start location we get got.
+ */
+ return rtems_filesystem_evaluate_relative_path( &pathname[i],
+ pathnamelen - i,
+ flags,
+ pathloc,
+ follow_link );
+}
+
+int rtems_filesystem_dirname(
+ const char *pathname
+)
+{
+ int len = strlen( pathname );
+
+ while ( len ) {
+ len--;
+ if ( rtems_filesystem_is_separator( pathname[len] ) )
+ break;
+ }
+
+ return len;
+}
+
+int rtems_filesystem_prefix_separators(
+ const char *pathname,
+ int pathnamelen
+)
+{
+ /*
+ * Eat any separators at start of the path.
+ */
+ int stripped = 0;
+ while ( *pathname && pathnamelen && rtems_filesystem_is_separator( *pathname ) )
+ {
+ pathname++;
+ pathnamelen--;
+ stripped++;
+ }
+ return stripped;
+}
diff --git a/cpukit/libcsupport/src/fchdir.c b/cpukit/libcsupport/src/fchdir.c
new file mode 100644
index 0000000000..3c53d653e3
--- /dev/null
+++ b/cpukit/libcsupport/src/fchdir.c
@@ -0,0 +1,82 @@
+/*
+ * fchdir() - compatible with SVr4, 4.4BSD and X/OPEN - Change Directory
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fchdir(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc, saved;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fchmod().
+ */
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) !=
+ RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+
+ /*
+ * FIXME : I feel there should be another call to
+ * actually take into account the extra reference to
+ * this node which we are making here. I can
+ * see the freenode interface but do not see
+ * allocnode node interface. It maybe node_type.
+ *
+ * FIXED: T.Straumann: it is evaluate_path()
+ * but note the race condition. Threads who
+ * share their rtems_filesystem_current better
+ * be synchronized!
+ */
+
+ saved = rtems_filesystem_current;
+ rtems_filesystem_current = iop->pathinfo;
+
+ /* clone the current node */
+ if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
+ /* cloning failed; restore original and bail out */
+ rtems_filesystem_current = saved;
+ return -1;
+ }
+ /* release the old one */
+ rtems_filesystem_freenode( &saved );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c
new file mode 100644
index 0000000000..867f40f1f8
--- /dev/null
+++ b/cpukit/libcsupport/src/fchmod.c
@@ -0,0 +1,45 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fchmod().
+ */
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode );
+}
diff --git a/cpukit/libcsupport/src/fchown.c b/cpukit/libcsupport/src/fchown.c
new file mode 100644
index 0000000000..13bb2b9da0
--- /dev/null
+++ b/cpukit/libcsupport/src/fchown.c
@@ -0,0 +1,42 @@
+/*
+ * fchown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fchown(
+ int fd,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ return (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group );
+}
diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c
new file mode 100644
index 0000000000..988a9414ee
--- /dev/null
+++ b/cpukit/libcsupport/src/fcntl.c
@@ -0,0 +1,184 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+static int vfcntl(
+ int fd,
+ int cmd,
+ va_list ap
+)
+{
+ rtems_libio_t *iop;
+ rtems_libio_t *diop;
+ int fd2;
+ int flags;
+ int mask;
+ int ret = 0;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fcntl().
+ */
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ fd2 = va_arg( ap, int );
+ if ( fd2 )
+ diop = rtems_libio_iop( fd2 );
+ else {
+ /* allocate a file control block */
+ diop = rtems_libio_allocate();
+ if ( diop == 0 ) {
+ ret = -1;
+ break;
+ }
+ }
+
+ diop->flags = iop->flags;
+ diop->pathinfo = iop->pathinfo;
+ ret = (int) (diop - rtems_libio_iops);
+ break;
+
+ case F_GETFD: /* get f_flags */
+ ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
+ break;
+
+ 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;
+ break;
+
+ case F_GETFL: /* more flags (cloexec) */
+ ret = rtems_libio_to_fcntl_flags( iop->flags );
+ break;
+
+ case F_SETFL:
+ flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
+ mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
+
+ /*
+ * XXX If we are turning on append, should we seek to the end?
+ */
+
+ iop->flags = (iop->flags & ~mask) | (flags & mask);
+ break;
+
+ case F_GETLK:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETLK:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETLKW:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETOWN: /* for sockets. */
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_GETOWN: /* for sockets. */
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ default:
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * If we got this far successfully, then we give the optional
+ * filesystem specific handler a chance to process this.
+ */
+
+ if (ret >= 0) {
+ int err = (*iop->pathinfo.handlers->fcntl_h)( cmd, iop );
+ if (err) {
+ errno = err;
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ int ret;
+ va_list ap;
+ va_start( ap, cmd );
+ ret = vfcntl(fd,cmd,ap);
+ va_end(ap);
+ return ret;
+}
+
+
+/*
+ * _fcntl_r
+ *
+ * This is the Newlib dependent reentrant version of fcntl().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_FCNTL_R)
+
+#include <reent.h>
+
+int _fcntl_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd,
+ int cmd,
+ int arg
+)
+{
+ return fcntl( fd, cmd, arg );
+}
+#endif
diff --git a/cpukit/libcsupport/src/fdatasync.c b/cpukit/libcsupport/src/fdatasync.c
new file mode 100644
index 0000000000..de226af5c1
--- /dev/null
+++ b/cpukit/libcsupport/src/fdatasync.c
@@ -0,0 +1,39 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ return (*iop->pathinfo.handlers->fdatasync_h)( iop );
+}
diff --git a/cpukit/libcsupport/src/flockfile.c b/cpukit/libcsupport/src/flockfile.c
new file mode 100644
index 0000000000..db83961af1
--- /dev/null
+++ b/cpukit/libcsupport/src/flockfile.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 by
+ * Ralf Corsépius, Ulm, Germany. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_FLOCKFILE) && defined(HAVE_DECL_FLOCKFILE)
+
+#include <stdio.h>
+
+/* This is a non-functional stub */
+void flockfile(FILE* file)
+{
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/fpathconf.c b/cpukit/libcsupport/src/fpathconf.c
new file mode 100644
index 0000000000..accaae1585
--- /dev/null
+++ b/cpukit/libcsupport/src/fpathconf.c
@@ -0,0 +1,87 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.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;
+
+ rtems_libio_check_fd(fd);
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ /*
+ * Now process the information request.
+ */
+
+ 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:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/cpukit/libcsupport/src/free.c b/cpukit/libcsupport/src/free.c
new file mode 100644
index 0000000000..d3ee2937f9
--- /dev/null
+++ b/cpukit/libcsupport/src/free.c
@@ -0,0 +1,55 @@
+/*
+ * calloc()
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+#include <stdlib.h>
+
+void free(
+ void *ptr
+)
+{
+ MSBUMP(free_calls, 1);
+
+ if ( !ptr )
+ return;
+
+ /*
+ * Do not attempt to free memory if in a critical section or ISR.
+ */
+ if ( _System_state_Is_up(_System_state_Get()) &&
+ !malloc_is_system_state_OK() ) {
+ malloc_deferred_free(ptr);
+ return;
+ }
+
+ /*
+ * If configured, update the statistics
+ */
+ if ( rtems_malloc_statistics_helpers )
+ (*rtems_malloc_statistics_helpers->at_free)(ptr);
+
+ if ( !_Protected_heap_Free( RTEMS_Malloc_Heap, ptr ) ) {
+ printk( "Program heap: free of bad pointer %p -- range %p - %p \n",
+ ptr,
+ RTEMS_Malloc_Heap->area_begin,
+ RTEMS_Malloc_Heap->area_end
+ );
+ }
+
+}
+#endif
diff --git a/cpukit/libcsupport/src/freenode.c b/cpukit/libcsupport/src/freenode.c
new file mode 100644
index 0000000000..21a9c1de91
--- /dev/null
+++ b/cpukit/libcsupport/src/freenode.c
@@ -0,0 +1,20 @@
+/*
+ * freenode()
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <rtems/libio_.h>
+
+void rtems_filesystem_freenode( rtems_filesystem_location_info_t *_node )
+{
+ _node->ops->freenod_h(_node );
+}
diff --git a/cpukit/libcsupport/src/fstat.c b/cpukit/libcsupport/src/fstat.c
new file mode 100644
index 0000000000..0718c28d0d
--- /dev/null
+++ b/cpukit/libcsupport/src/fstat.c
@@ -0,0 +1,72 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+ if ( !sbuf )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Now process the stat() request.
+ */
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ return (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_FSTAT_R)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/fsync.c b/cpukit/libcsupport/src/fsync.c
new file mode 100644
index 0000000000..4d2fe2ae12
--- /dev/null
+++ b/cpukit/libcsupport/src/fsync.c
@@ -0,0 +1,39 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the fsync().
+ */
+
+ return (*iop->pathinfo.handlers->fsync_h)( iop );
+}
diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c
new file mode 100644
index 0000000000..64946d7bb6
--- /dev/null
+++ b/cpukit/libcsupport/src/ftruncate.c
@@ -0,0 +1,51 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ return (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
+}
diff --git a/cpukit/libcsupport/src/ftrylockfile.c b/cpukit/libcsupport/src/ftrylockfile.c
new file mode 100644
index 0000000000..924690e44f
--- /dev/null
+++ b/cpukit/libcsupport/src/ftrylockfile.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 by
+ * Ralf Corsépius, Ulm, Germany. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_FTRYLOCKFILE) && defined(HAVE_DECL_FTRYLOCKFILE)
+
+#include <stdio.h>
+#include <rtems/seterr.h>
+#include <errno.h>
+
+/* This is a non-functional stub */
+int ftrylockfile(FILE* file)
+{
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/funlockfile.c b/cpukit/libcsupport/src/funlockfile.c
new file mode 100644
index 0000000000..a9f1bf3a92
--- /dev/null
+++ b/cpukit/libcsupport/src/funlockfile.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 by
+ * Ralf Corsépius, Ulm, Germany. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_FUNLOCKFILE) && defined(HAVE_DECL_FUNLOCKFILE)
+
+#include <stdio.h>
+
+/* This is a non-functional stub */
+void funlockfile(FILE* file)
+{
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/getchark.c b/cpukit/libcsupport/src/getchark.c
new file mode 100644
index 0000000000..f501fc65f0
--- /dev/null
+++ b/cpukit/libcsupport/src/getchark.c
@@ -0,0 +1,25 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+
+int getchark(void)
+{
+ if ( BSP_poll_char )
+ return (*BSP_poll_char)();
+
+ return -1;
+}
diff --git a/cpukit/libcsupport/src/getcwd.c b/cpukit/libcsupport/src/getcwd.c
new file mode 100644
index 0000000000..2f2be7fc72
--- /dev/null
+++ b/cpukit/libcsupport/src/getcwd.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1989, 1991 The 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.
+ *
+ * Copied from newlib 1.8.1. RTEMS can not build all of the contents
+ * of the UNIX directory but we need this routine.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_GETCWD
+
+/*
+ * Added these when moved to RTEMS
+ */
+
+#define _stat stat
+#define _opendir opendir
+#define _fstat fstat
+#define _readdir readdir
+#define _closedir closedir
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getcwd.c 5.11 (Berkeley) 2/24/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <reent.h>
+#include <_syslist.h>
+
+#define bcopy(a,b,c) memmove (b,a,c)
+
+#define ISDOT(dp) \
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+
+#ifndef _REENT_ONLY
+
+char *
+getcwd (
+ char *pt,
+ size_t size)
+{
+ register struct dirent *dp;
+ register DIR *dir = 0;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+ int save_errno;
+ char *ept, *eup, *up;
+
+ /*
+ * If no buffer specified by the user, allocate one as necessary.
+ * If a buffer is specified, the size has to be non-zero. The path
+ * is built from the end of the buffer backwards.
+ */
+
+ if (pt)
+ {
+ ptsize = 0;
+ if (!size)
+ {
+ errno = EINVAL;
+ return (char *) NULL;
+ }
+ ept = pt + size;
+ }
+ else
+ {
+ if (!(pt = (char *) malloc (ptsize = 1024 - 4)))
+ {
+ return (char *) NULL;
+ }
+ ept = pt + ptsize;
+ }
+ bpt = ept - 1;
+ *bpt = '\0';
+
+ /*
+ * Allocate bytes (1024 - malloc space) for the string of "../"'s.
+ * Should always be enough (it's 340 levels). If it's not, allocate
+ * as necessary. Special * case the first stat, it's ".", not "..".
+ */
+
+ if (!(up = (char *) malloc (upsize = 1024 - 4)))
+ {
+ goto err;
+ }
+ eup = up + MAXPATHLEN;
+ bup = up;
+ up[0] = '.';
+ up[1] = '\0';
+
+ /* Save root values, so know when to stop. */
+ if (stat ("/", &s))
+ goto err;
+ root_dev = s.st_dev;
+ root_ino = s.st_ino;
+
+ errno = 0; /* XXX readdir has no error return. */
+
+ for (first = 1;; first = 0)
+ {
+ /* Stat the current level. */
+ if (_stat (up, &s))
+ goto err;
+
+ /* Save current node values. */
+ ino = s.st_ino;
+ dev = s.st_dev;
+
+ /* Check for reaching root. */
+ if (root_dev == dev && root_ino == ino)
+ {
+ *--bpt = '/';
+ /*
+ * It's unclear that it's a requirement to copy the
+ * path to the beginning of the buffer, but it's always
+ * been that way and stuff would probably break.
+ */
+ (void) bcopy (bpt, pt, ept - bpt);
+ free (up);
+ return pt;
+ }
+
+ /*
+ * Build pointer to the parent directory, allocating memory
+ * as necessary. Max length is 3 for "../", the largest
+ * possible component name, plus a trailing NULL.
+ */
+
+ if (bup + 3 + MAXNAMLEN + 1 >= eup)
+ {
+ if (!(up = (char *) realloc (up, upsize *= 2)))
+ {
+ goto err;
+ }
+ bup = up;
+ eup = up + upsize;
+ }
+ *bup++ = '.';
+ *bup++ = '.';
+ *bup = '\0';
+
+ /* Open and stat parent directory. */
+ if (!(dir = _opendir (up)) || _fstat (__dirfd (dir), &s))
+ goto err;
+
+ /* Add trailing slash for next directory. */
+ *bup++ = '/';
+
+ /*
+ * If it's a mount point, have to stat each element because
+ * the inode number in the directory is for the entry in the
+ * parent directory, not the inode number of the mounted file.
+ */
+
+ save_errno = 0;
+ if (s.st_dev == dev)
+ {
+ for (;;)
+ {
+ if (!(dp = _readdir (dir)))
+ goto notfound;
+ if (dp->d_ino == ino)
+ break;
+ }
+ }
+ else
+ for (;;)
+ {
+ if (!(dp = _readdir (dir)))
+ goto notfound;
+ if (ISDOT (dp))
+ continue;
+ bcopy (dp->d_name, bup, strlen (dp->d_name) + 1);
+
+ /* Save the first error for later. */
+ if (stat (up, &s))
+ {
+ if (!save_errno)
+ save_errno = errno;
+ errno = 0;
+ continue;
+ }
+ if (s.st_dev == dev && s.st_ino == ino)
+ break;
+ }
+
+ /*
+ * Check for length of the current name, preceding slash,
+ * leading slash.
+ */
+
+ if (bpt - pt <= strlen (dp->d_name) + (first ? 1 : 2))
+ {
+ size_t len, off;
+
+ if (!ptsize)
+ {
+ errno = ERANGE;
+ goto err;
+ }
+ off = bpt - pt;
+ len = ept - bpt;
+ if (!(pt = (char *) realloc (pt, ptsize *= 2)))
+ {
+ goto err;
+ }
+ bpt = pt + off;
+ ept = pt + ptsize;
+ (void) bcopy (bpt, ept - len, len);
+ bpt = ept - len;
+ }
+ if (!first)
+ *--bpt = '/';
+ bpt -= strlen (dp->d_name);
+ bcopy (dp->d_name, bpt, strlen (dp->d_name));
+ (void) _closedir (dir);
+ dir = 0;
+
+ /* Truncate any file name. */
+ *bup = '\0';
+ }
+
+notfound:
+ /*
+ * If readdir set errno, use it, not any saved error; otherwise,
+ * didn't find the current directory in its parent directory, set
+ * errno to ENOENT.
+ */
+
+ if (!errno)
+ errno = save_errno ? save_errno : ENOENT;
+ /* FALLTHROUGH */
+
+err:
+ if(dir)
+ (void) _closedir (dir);
+ if (ptsize)
+ free (pt);
+ free (up);
+ return (char *) NULL;
+}
+
+#endif /* _REENT_ONLY */
+
+#endif
diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c
new file mode 100644
index 0000000000..d0b787cd88
--- /dev/null
+++ b/cpukit/libcsupport/src/getdents.c
@@ -0,0 +1,55 @@
+/*
+ * 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-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+)
+{
+ 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_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+ return (*iop->pathinfo.handlers->read_h)( iop, dd_buf, dd_len );
+}
diff --git a/cpukit/libcsupport/src/getegid.c b/cpukit/libcsupport/src/getegid.c
new file mode 100644
index 0000000000..2d89348230
--- /dev/null
+++ b/cpukit/libcsupport/src/getegid.c
@@ -0,0 +1,24 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+
+/*
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+gid_t getegid( void )
+{
+ return _POSIX_types_Egid;
+}
diff --git a/cpukit/libcsupport/src/geteuid.c b/cpukit/libcsupport/src/geteuid.c
new file mode 100644
index 0000000000..de35557c63
--- /dev/null
+++ b/cpukit/libcsupport/src/geteuid.c
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+#include <rtems/userenv.h>
+
+/*
+ * MACRO in userenv.h
+uid_t _POSIX_types_Euid = 0;
+*/
+
+/*PAGE
+ *
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+uid_t geteuid( void )
+{
+ return _POSIX_types_Euid;
+}
diff --git a/cpukit/libcsupport/src/getgid.c b/cpukit/libcsupport/src/getgid.c
new file mode 100644
index 0000000000..7074e765e5
--- /dev/null
+++ b/cpukit/libcsupport/src/getgid.c
@@ -0,0 +1,18 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/userenv.h>
+
+/*
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+gid_t getgid( void )
+{
+ return _POSIX_types_Gid;
+}
diff --git a/cpukit/libcsupport/src/getgroups.c b/cpukit/libcsupport/src/getgroups.c
new file mode 100644
index 0000000000..128761c8b6
--- /dev/null
+++ b/cpukit/libcsupport/src/getgroups.c
@@ -0,0 +1,23 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/*PAGE
+ *
+ * 4.2.3 Get Supplementary IDs, P1003.1b-1993, p. 86
+ */
+
+int getgroups(
+ int gidsetsize __attribute__((unused)),
+ gid_t grouplist[] __attribute__((unused))
+)
+{
+ return 0; /* no supplemental group ids */
+}
diff --git a/cpukit/libcsupport/src/getlogin.c b/cpukit/libcsupport/src/getlogin.c
new file mode 100644
index 0000000000..f98e7ca9e0
--- /dev/null
+++ b/cpukit/libcsupport/src/getlogin.c
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+
+#include <unistd.h>
+#include <pwd.h>
+
+/*
+ * 4.2.4 Get User Name, P1003.1b-1993, p. 87
+ *
+ * NOTE: P1003.1c/D10, p. 49 adds getlogin_r().
+ */
+char *getlogin( void )
+{
+ (void) getlogin_r( _POSIX_types_Getlogin_buffer, LOGIN_NAME_MAX );
+ return _POSIX_types_Getlogin_buffer;
+}
+
+/*
+ * 4.2.4 Get User Name, P1003.1b-1993, p. 87
+ *
+ * NOTE: P1003.1c/D10, p. 49 adds getlogin_r().
+ */
+int getlogin_r(
+ char *name,
+ size_t namesize
+)
+{
+ struct passwd *pw;
+ char *pname;
+
+ if ( !name )
+ return EFAULT;
+
+ if ( namesize < LOGIN_NAME_MAX )
+ return ERANGE;
+
+ /* Set the pointer to a default name */
+ pname = "";
+
+ pw = getpwuid(getuid());
+ if ( pw )
+ pname = pw->pw_name;
+
+ strncpy( name, pname, LOGIN_NAME_MAX );
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/getpagesize.c b/cpukit/libcsupport/src/getpagesize.c
new file mode 100644
index 0000000000..3ea44be1fa
--- /dev/null
+++ b/cpukit/libcsupport/src/getpagesize.c
@@ -0,0 +1,22 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/param.h>
+
+/*
+ * Get System Page Size (from SVR4 and 4.2+ BSD)
+ *
+ * This is not a functional version but the SPARC backend for at least
+ * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and
+ * return a reasonable value.
+ */
+int getpagesize(void)
+{
+ return PAGE_SIZE;
+}
diff --git a/cpukit/libcsupport/src/getpgrp.c b/cpukit/libcsupport/src/getpgrp.c
new file mode 100644
index 0000000000..0904d23883
--- /dev/null
+++ b/cpukit/libcsupport/src/getpgrp.c
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.1 Get Process Group IDs, P1003.1b-1993, p. 89
+ */
+
+pid_t getpgrp( void )
+{
+ /*
+ * This always succeeds and returns the process group id. For rtems,
+ * this will always be the local node;
+ */
+
+ return _Objects_Local_node;
+}
diff --git a/cpukit/libcsupport/src/getpid.c b/cpukit/libcsupport/src/getpid.c
new file mode 100644
index 0000000000..55cd2a6589
--- /dev/null
+++ b/cpukit/libcsupport/src/getpid.c
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.1.1 Get Process and Parent Process IDs, P1003.1b-1993, p. 83
+ */
+
+pid_t getpid( void )
+{
+ return _Objects_Local_node;
+}
+
+/*
+ * _getpid_r
+ *
+ * This is the Newlib dependent reentrant version of getpid().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__GETPID_R)
+
+#include <reent.h>
+
+pid_t _getpid_r(
+ struct _reent *ptr __attribute__((unused))
+)
+{
+ return getpid();
+}
+#endif
diff --git a/cpukit/libcsupport/src/getppid.c b/cpukit/libcsupport/src/getppid.c
new file mode 100644
index 0000000000..b987f69447
--- /dev/null
+++ b/cpukit/libcsupport/src/getppid.c
@@ -0,0 +1,25 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+pid_t _POSIX_types_Ppid = 0;
+
+/*PAGE
+ *
+ * 4.1.1 Get Process and Parent Process IDs, P1003.1b-1993, p. 83
+ */
+
+pid_t getppid( void )
+{
+ return _POSIX_types_Ppid;
+}
diff --git a/cpukit/libcsupport/src/getpwent.c b/cpukit/libcsupport/src/getpwent.c
new file mode 100644
index 0000000000..210f4bedd5
--- /dev/null
+++ b/cpukit/libcsupport/src/getpwent.c
@@ -0,0 +1,438 @@
+/*
+ * POSIX 1003.1b - 9.2.2 - User Database Access Routines
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * Static, thread-unsafe, buffers
+ */
+static FILE *passwd_fp;
+static char pwbuf[200];
+static struct passwd pwent;
+static FILE *group_fp;
+static char grbuf[200];
+static struct group grent;
+
+/*
+ * Initialize useable but dummy databases
+ */
+void init_etc_passwd_group(void)
+{
+ FILE *fp;
+ static char etc_passwd_initted = 0;
+
+ if (etc_passwd_initted)
+ return;
+ etc_passwd_initted = 1;
+ mkdir("/etc", 0777);
+
+ /*
+ * Initialize /etc/passwd
+ */
+ if ((fp = fopen("/etc/passwd", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/passwd", "w")) != NULL) {
+ fprintf(fp, "root:*:0:0:root::/:/bin/sh\n"
+ "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
+ "tty:!:2:2:tty owner::/:/bin/false\n" );
+ fclose(fp);
+ }
+
+ /*
+ * Initialize /etc/group
+ */
+ if ((fp = fopen("/etc/group", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/group", "w")) != NULL) {
+ fprintf( fp, "root:x:0:root\n"
+ "rtems:x:1:rtems\n"
+ "tty:x:2:tty\n" );
+ fclose(fp);
+ }
+}
+
+/*
+ * Extract a string value from the database
+ */
+static int
+scanString(FILE *fp, char **name, char **bufp, size_t *nleft, int nlFlag)
+{
+ int c;
+
+ *name = *bufp;
+ for (;;) {
+ c = getc(fp);
+ if (c == ':') {
+ if (nlFlag)
+ return 0;
+ break;
+ }
+ if (c == '\n') {
+ if (!nlFlag)
+ return 0;
+ break;
+ }
+ if (c == EOF)
+ return 0;
+ if (*nleft < 2)
+ return 0;
+ **bufp = c;
+ ++(*bufp);
+ --(*nleft);
+ }
+ **bufp = '\0';
+ ++(*bufp);
+ --(*nleft);
+ return 1;
+}
+
+/*
+ * Extract an integer value from the database
+ */
+static int
+scanInt(FILE *fp, int *val)
+{
+ int c;
+ unsigned int i = 0;
+ unsigned int limit = INT_MAX;
+ int sign = 0;
+ int d;
+
+ for (;;) {
+ c = getc(fp);
+ if (c == ':')
+ break;
+ if (sign == 0) {
+ if (c == '-') {
+ sign = -1;
+ limit++;
+ continue;
+ }
+ sign = 1;
+ }
+ if (!isdigit(c))
+ return 0;
+ d = c - '0';
+ if ((i > (limit / 10))
+ || ((i == (limit / 10)) && (d > (limit % 10))))
+ return 0;
+ i = i * 10 + d;
+ }
+ if (sign == 0)
+ return 0;
+ *val = i * sign;
+ return 1;
+}
+
+/*
+ * Extract a single password record from the database
+ */
+static int scanpw(
+ FILE *fp,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int pwuid, pwgid;
+
+ if (!scanString(fp, &pwd->pw_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &pwuid)
+ || !scanInt(fp, &pwgid)
+ || !scanString(fp, &pwd->pw_comment, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_gecos, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_dir, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_shell, &buffer, &bufsize, 1))
+ return 0;
+ pwd->pw_uid = pwuid;
+ pwd->pw_gid = pwgid;
+ return 1;
+}
+
+static int getpw_r(
+ const char *name,
+ int uid,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ FILE *fp;
+ int match;
+
+ init_etc_passwd_group();
+
+ if ((fp = fopen("/etc/passwd", "r")) == NULL)
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ for(;;) {
+ if (!scanpw(fp, pwd, buffer, bufsize))
+ goto error_einval;
+
+ if (name) {
+ match = (strcmp(pwd->pw_name, name) == 0);
+ } else {
+ match = (pwd->pw_uid == uid);
+ }
+
+ if (match) {
+ fclose(fp);
+ *result = pwd;
+ return 0;
+ }
+ }
+error_einval:
+ fclose(fp);
+ rtems_set_errno_and_return_minus_one( EINVAL );
+}
+
+int getpwnam_r(
+ const char *name,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ return getpw_r(name, 0, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwnam(
+ const char *name
+)
+{
+ struct passwd *p;
+
+ if(getpwnam_r(name, &pwent, pwbuf, sizeof pwbuf, &p))
+ return NULL;
+ return p;
+}
+
+int getpwuid_r(
+ uid_t uid,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwuid(
+ uid_t uid
+)
+{
+ struct passwd *p;
+
+ if(getpwuid_r(uid, &pwent, pwbuf, sizeof pwbuf, &p))
+ return NULL;
+ return p;
+}
+
+struct passwd *getpwent(void)
+{
+ if (passwd_fp == NULL)
+ return NULL;
+ if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
+ return NULL;
+ return &pwent;
+}
+
+void setpwent(void)
+{
+ init_etc_passwd_group();
+
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+ passwd_fp = fopen("/etc/passwd", "r");
+}
+
+void endpwent(void)
+{
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+}
+
+/*
+ * Extract a single group record from the database
+ */
+static int scangr(
+ FILE *fp,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int grgid;
+ char *grmem, *cp;
+ int memcount;
+
+ if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &grgid)
+ || !scanString(fp, &grmem, &buffer, &bufsize, 1))
+ return 0;
+ grp->gr_gid = grgid;
+
+ /*
+ * Determine number of members
+ */
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',')
+ memcount++;
+ }
+
+ /*
+ * Hack to produce (hopefully) a suitably-aligned array of pointers
+ */
+ if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
+ return 0;
+ grp->gr_mem = (char **)(((uintptr_t)buffer + 15) & ~15);
+
+ /*
+ * Fill in pointer array
+ */
+ grp->gr_mem[0] = grmem;
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',') {
+ *cp = '\0';
+ grp->gr_mem[memcount++] = cp + 1;
+ }
+ }
+ grp->gr_mem[memcount] = NULL;
+ return 1;
+}
+
+static int getgr_r(
+ const char *name,
+ int gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ FILE *fp;
+ int match;
+
+ init_etc_passwd_group();
+
+ if ((fp = fopen("/etc/group", "r")) == NULL)
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ for(;;) {
+ if (!scangr(fp, grp, buffer, bufsize))
+ goto error_einval;
+
+ if (name) {
+ match = (strcmp(grp->gr_name, name) == 0);
+ } else {
+ match = (grp->gr_gid == gid);
+ }
+
+ if (match) {
+ fclose(fp);
+ *result = grp;
+ return 0;
+ }
+ }
+error_einval:
+ fclose(fp);
+ rtems_set_errno_and_return_minus_one( EINVAL );
+}
+
+int getgrnam_r(
+ const char *name,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ return getgr_r(name, 0, grp, buffer, bufsize, result);
+}
+
+struct group *getgrnam(
+ const char *name
+)
+{
+ struct group *p;
+
+ if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
+ return NULL;
+ return p;
+}
+
+int getgrgid_r(
+ gid_t gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ return getgr_r(NULL, gid, grp, buffer, bufsize, result);
+}
+
+struct group *getgrgid(
+ gid_t gid
+)
+{
+ struct group *p;
+
+ if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
+ return NULL;
+ return p;
+}
+
+struct group *getgrent(void)
+{
+ if (group_fp == NULL)
+ return NULL;
+ if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
+ return NULL;
+ return &grent;
+}
+
+void setgrent(void)
+{
+ init_etc_passwd_group();
+
+ if (group_fp != NULL)
+ fclose(group_fp);
+ group_fp = fopen("/etc/group", "r");
+}
+
+void endgrent(void)
+{
+ if (group_fp != NULL)
+ fclose(group_fp);
+}
diff --git a/cpukit/libcsupport/src/getrusage.c b/cpukit/libcsupport/src/getrusage.c
new file mode 100644
index 0000000000..df68376e50
--- /dev/null
+++ b/cpukit/libcsupport/src/getrusage.c
@@ -0,0 +1,54 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/resource.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/seterr.h>
+
+int getrusage(int who, struct rusage *usage)
+{
+ struct timespec uptime;
+ struct timeval rtime;
+
+ if ( !usage )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * RTEMS only has a single process so there are no children.
+ * The single process has been running since the system
+ * was booted and since there is no distinction between system
+ * and user time, we will just report the uptime.
+ */
+ if (who == RUSAGE_SELF) {
+ rtems_clock_get_uptime( &uptime );
+
+ rtime.tv_sec = uptime.tv_sec;
+ rtime.tv_usec = uptime.tv_nsec / 1000;
+
+ usage->ru_utime = rtime;
+ usage->ru_stime = rtime;
+
+ return 0;
+ }
+
+ if (who == RUSAGE_CHILDREN) {
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+ }
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+}
+
diff --git a/cpukit/libcsupport/src/getuid.c b/cpukit/libcsupport/src/getuid.c
new file mode 100644
index 0000000000..d3a13192fa
--- /dev/null
+++ b/cpukit/libcsupport/src/getuid.c
@@ -0,0 +1,28 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/userenv.h>
+
+/*
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+uid_t getuid( void )
+{
+ return _POSIX_types_Uid;
+}
+
diff --git a/cpukit/libcsupport/src/gxx_wrappers.c b/cpukit/libcsupport/src/gxx_wrappers.c
new file mode 100644
index 0000000000..e3d300a9f2
--- /dev/null
+++ b/cpukit/libcsupport/src/gxx_wrappers.c
@@ -0,0 +1,295 @@
+/*
+ * RTEMS threads compatibility routines for libgcc2.
+ *
+ * by: Rosimildo da Silva (rdasilva@connecttel.com)
+ *
+ * Used ideas from:
+ * W. Eric Norum
+ * Canadian Light Source
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@cls.usask.ca
+ *
+ * Eric sent some e-mail in the rtems-list as a start point for this
+ * module implementation.
+ *
+ * $Id$
+ */
+
+/*
+ * This file is only used if using gcc
+ */
+#if defined(__GNUC__)
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/gxx_wrappers.h>
+
+#include <stdlib.h>
+
+#include <rtems.h>
+
+/* uncomment this if you need to debug this interface */
+/*#define DEBUG_GXX_WRAPPERS 1*/
+
+int rtems_gxx_once(__gthread_once_t *once, void (*func) (void))
+{
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: once=%x, func=%x\n", *once, func );
+ #endif
+
+ if ( *(volatile __gthread_once_t *)once == 0 ) {
+ rtems_mode saveMode;
+ __gthread_once_t o;
+
+ rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
+ if ( (o = *(volatile __gthread_once_t *)once) == 0 ) {
+ *(volatile __gthread_once_t *)once = 1;
+ }
+ rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
+ if ( o == 0 )
+ (*func)();
+ }
+ return 0;
+}
+
+int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *))
+{
+ rtems_status_code status;
+
+ /* Ok, this can be a bit tricky. We are going to return a "key" as a
+ * pointer to the buffer that will hold the value of the key itself.
+ * We have to to this, because the others functions on this interface
+ * deal with the value of the key, as used with the POSIX API.
+ */
+ /* Do not pull your hair, trust me this works. :-) */
+ __gthread_key_t new_key = (__gthread_key_t) malloc( sizeof( *new_key ) );
+ *key = new_key;
+ new_key->val = NULL;
+ new_key->dtor = dtor;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk(
+ "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key
+ );
+ #endif
+
+ /* register with RTEMS the buffer that will hold the key values */
+ status = rtems_task_variable_add( RTEMS_SELF, (void **)new_key, dtor );
+ if ( status == RTEMS_SUCCESSFUL )
+ return 0;
+
+ free( new_key );
+ return -1;
+}
+
+int rtems_gxx_key_dtor (__gthread_key_t key, void *ptr)
+{
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
+ #endif
+
+ key->val = 0;
+ return 0;
+}
+
+int rtems_gxx_key_delete (__gthread_key_t key)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: delete key=%x\n", key );
+ #endif
+
+ /* register with RTEMS the buffer that will hold the key values */
+ status = rtems_task_variable_delete( RTEMS_SELF, (void **)key );
+ if ( status == RTEMS_SUCCESSFUL ) {
+ /* Hmm - hopefully all tasks using this key have gone away... */
+ if ( key ) free( *(void **)key );
+ return 0;
+ }
+ key = NULL;
+ return 0;
+}
+
+void *rtems_gxx_getspecific(__gthread_key_t key)
+{
+ rtems_status_code status;
+ void *p= 0;
+
+ /* register with RTEMS the buffer that will hold the key values */
+ status = rtems_task_variable_get( RTEMS_SELF, (void **)key, &p );
+ if ( status == RTEMS_SUCCESSFUL ) {
+ /* We do not have to do this, but what the heck ! */
+ p= key->val;
+ } else {
+ /* fisrt time, always set to zero, it is unknown the value that the others
+ * threads are using at the moment of this call
+ */
+ status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_GXX_KEY_ADD_FAILED
+ );
+ }
+ key->val = (void *)0;
+ }
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk(
+ "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n",
+ key,
+ p,
+ rtems_task_self()
+ );
+ #endif
+ return p;
+}
+
+int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk(
+ "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n",
+ key,
+ ptr,
+ rtems_task_self()
+ );
+ #endif
+
+ /* register with RTEMS the buffer that will hold the key values */
+ status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor );
+ if ( status == RTEMS_SUCCESSFUL ) {
+ /* now let's set the proper value */
+ key->val = (void *)ptr;
+ return 0;
+ }
+ return -1;
+}
+
+
+/*
+ * MUTEX support
+ */
+void rtems_gxx_mutex_init (__gthread_mutex_t *mutex)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: mutex init =%X\n", *mutex );
+ #endif
+
+ status = rtems_semaphore_create(
+ rtems_build_name ('G', 'C', 'C', '2'),
+ 1,
+ RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE|
+ RTEMS_INHERIT_PRIORITY|RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
+ 0,
+ (rtems_id *)mutex
+ );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk(
+ "gxx_wrappers: mutex init failed %s (%d)\n",
+ rtems_status_text(status),
+ status
+ );
+ #endif
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED
+ );
+ }
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: mutex init complete =%X\n", *mutex );
+ #endif
+}
+
+int rtems_gxx_mutex_lock (__gthread_mutex_t *mutex)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: lock mutex=%X\n", *mutex );
+ #endif
+
+ status = rtems_semaphore_obtain(
+ *(rtems_id *)mutex,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT
+ );
+ if ( status == RTEMS_SUCCESSFUL )
+ return 0;
+ return -1;
+}
+
+int rtems_gxx_mutex_destroy (__gthread_mutex_t *mutex)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: destroy mutex=%X\n", *mutex );
+ #endif
+
+ status = rtems_semaphore_delete(*(rtems_id *)mutex);
+ if ( status == RTEMS_SUCCESSFUL )
+ return 0;
+ return -1;
+}
+
+int rtems_gxx_mutex_trylock (__gthread_mutex_t *mutex)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: trylock mutex=%X\n", *mutex );
+ #endif
+
+ status = rtems_semaphore_obtain (*(rtems_id *)mutex, RTEMS_NO_WAIT, 0);
+ if ( status == RTEMS_SUCCESSFUL )
+ return 0;
+ return -1;
+}
+
+int rtems_gxx_mutex_unlock (__gthread_mutex_t *mutex)
+{
+ rtems_status_code status;
+
+ #ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: unlock mutex=%X\n", *mutex );
+ #endif
+
+ status = rtems_semaphore_release( *(rtems_id *)mutex );
+ if ( status == RTEMS_SUCCESSFUL )
+ return 0;
+ return -1;
+}
+
+void rtems_gxx_recursive_mutex_init(__gthread_recursive_mutex_t *mutex)
+{
+ rtems_gxx_mutex_init(mutex);
+}
+
+int rtems_gxx_recursive_mutex_lock(__gthread_recursive_mutex_t *mutex)
+{
+ return rtems_gxx_mutex_lock(mutex);
+}
+
+int rtems_gxx_recursive_mutex_trylock(__gthread_recursive_mutex_t *mutex)
+{
+ return rtems_gxx_mutex_trylock(mutex);
+}
+
+int rtems_gxx_recursive_mutex_unlock(__gthread_recursive_mutex_t *mutex)
+{
+ return rtems_gxx_mutex_unlock(mutex);
+}
+
+#endif /* __GNUC__ */
diff --git a/cpukit/libcsupport/src/ioctl.c b/cpukit/libcsupport/src/ioctl.c
new file mode 100644
index 0000000000..ae8a88bd77
--- /dev/null
+++ b/cpukit/libcsupport/src/ioctl.c
@@ -0,0 +1,54 @@
+/*
+ * 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-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <unistd.h>
+
+int ioctl(
+ int fd,
+ ioctl_command_t command,
+ ...
+)
+{
+ va_list ap;
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+ void *buffer;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ va_start(ap, command);
+
+ buffer = va_arg(ap, void *);
+
+ /*
+ * Now process the ioctl().
+ */
+ rc = (*iop->pathinfo.handlers->ioctl_h)( iop, command, buffer );
+
+ va_end( ap );
+ return rc;
+}
diff --git a/cpukit/libcsupport/src/isatty.c b/cpukit/libcsupport/src/isatty.c
new file mode 100644
index 0000000000..b29ce7b53d
--- /dev/null
+++ b/cpukit/libcsupport/src/isatty.c
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_ISATTY
+
+#include <sys/stat.h>
+
+int isatty(
+ int fd
+)
+{
+ struct stat buf;
+
+ if (fstat (fd, &buf) < 0)
+ return 0;
+
+ if (S_ISCHR (buf.st_mode))
+ return 1;
+
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/isatty_r.c b/cpukit/libcsupport/src/isatty_r.c
new file mode 100644
index 0000000000..3e2e2baa14
--- /dev/null
+++ b/cpukit/libcsupport/src/isatty_r.c
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * _isatty_r
+ *
+ * This is the Newlib dependent reentrant version of isatty().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__ISATTY_R)
+
+#include <unistd.h>
+#include <reent.h>
+#include <sys/stat.h>
+
+int _isatty_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd
+)
+{
+ return isatty( fd );
+}
+#endif
diff --git a/cpukit/libcsupport/src/issetugid.c b/cpukit/libcsupport/src/issetugid.c
new file mode 100644
index 0000000000..84a2d9ce61
--- /dev/null
+++ b/cpukit/libcsupport/src/issetugid.c
@@ -0,0 +1,16 @@
+/*
+ * Dummy version of BSD routine
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_ISSETUGID)
+int issetugid (void)
+{
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/kill_noposix.c b/cpukit/libcsupport/src/kill_noposix.c
new file mode 100644
index 0000000000..8b7898b3f8
--- /dev/null
+++ b/cpukit/libcsupport/src/kill_noposix.c
@@ -0,0 +1,48 @@
+/*
+ * Marginal implementations of some POSIX API routines
+ * to be used when POSIX is disabled.
+ *
+ * + kill
+ * + _kill_r
+ * + __kill
+ * + sleep
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+
+/*
+ * These are directly supported (and completely correct) in the posix api.
+ */
+
+#if !defined(RTEMS_POSIX_API)
+int kill( pid_t pid, int sig )
+{
+ return 0;
+}
+
+#if defined(RTEMS_NEWLIB)
+#include <reent.h>
+
+int _kill_r( struct _reent *ptr, pid_t pid, int sig )
+{
+ return 0;
+}
+#endif
+
+int __kill( pid_t pid, int sig )
+{
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/lchown.c b/cpukit/libcsupport/src/lchown.c
new file mode 100644
index 0000000000..c244e08879
--- /dev/null
+++ b/cpukit/libcsupport/src/lchown.c
@@ -0,0 +1,31 @@
+/*
+ * lchown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ * But Do Not Follow a Symlink
+ *
+ * Written by: Vinu Rajashekhar <vinutheraj@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+
+#include <rtems.h>
+
+int _chown_helper( const char *path, uid_t owner, gid_t group, int follow_link);
+
+int lchown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ return _chown_helper( path, owner, group, false );
+}
diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c
new file mode 100644
index 0000000000..d080d01596
--- /dev/null
+++ b/cpukit/libcsupport/src/libio.c
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/assoc.h>
+
+/* define this to alias O_NDELAY to O_NONBLOCK, i.e.,
+ * O_NDELAY is accepted on input but fcntl(F_GETFL) returns
+ * O_NONBLOCK. This is because rtems has no distinction
+ * between the two (but some systems have).
+ * Note that accepting this alias creates a problem:
+ * an application trying to clear the non-blocking flag
+ * using a
+ *
+ * fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NDELAY);
+ *
+ * does (silently) ignore the operation.
+ */
+#undef ACCEPT_O_NDELAY_ALIAS
+
+/*
+ * rtems_libio_fcntl_flags
+ *
+ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
+ */
+
+const 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 },
+};
+
+const rtems_assoc_t status_flags_assoc[] = {
+#ifdef ACCEPT_O_NDELAY_ALIAS
+ { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
+#endif
+ { "NONBLOCK", LIBIO_FLAGS_NO_DELAY, O_NONBLOCK },
+ { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
+ { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
+ { 0, 0, 0 },
+};
+
+uint32_t rtems_libio_fcntl_flags(
+ uint32_t fcntl_flags
+)
+{
+ uint32_t flags = 0;
+ uint32_t 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
+ */
+
+ flags |=
+ rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ return flags;
+}
+
+/*
+ * rtems_libio_to_fcntl_flags
+ *
+ * Convert RTEMS internal flags to UNIX fnctl(2) flags
+ */
+
+uint32_t rtems_libio_to_fcntl_flags(
+ uint32_t flags
+)
+{
+ uint32_t fcntl_flags = 0;
+
+ if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
+ fcntl_flags |= O_RDWR;
+ } else if ( (flags & LIBIO_FLAGS_READ) == LIBIO_FLAGS_READ) {
+ fcntl_flags |= O_RDONLY;
+ } else if ( (flags & LIBIO_FLAGS_WRITE) == LIBIO_FLAGS_WRITE) {
+ fcntl_flags |= O_WRONLY;
+ }
+
+ if ( (flags & LIBIO_FLAGS_NO_DELAY) == LIBIO_FLAGS_NO_DELAY ) {
+ fcntl_flags |= O_NONBLOCK;
+ }
+
+ if ( (flags & LIBIO_FLAGS_APPEND) == LIBIO_FLAGS_APPEND ) {
+ fcntl_flags |= O_APPEND;
+ }
+
+ if ( (flags & LIBIO_FLAGS_CREATE) == LIBIO_FLAGS_CREATE ) {
+ fcntl_flags |= O_CREAT;
+ }
+
+ return fcntl_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.
+ */
+
+rtems_libio_t *rtems_libio_allocate( void )
+{
+ rtems_libio_t *iop, *next;
+ rtems_status_code rc;
+ rtems_id sema;
+
+ rtems_libio_lock();
+
+ if (rtems_libio_iop_freelist) {
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_IOP_SEM(rtems_libio_iop_freelist - rtems_libio_iops),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ 0,
+ &sema
+ );
+ if (rc != RTEMS_SUCCESSFUL)
+ goto failed;
+ iop = rtems_libio_iop_freelist;
+ next = iop->data1;
+ (void) memset( iop, 0, sizeof(rtems_libio_t) );
+ iop->flags = LIBIO_FLAGS_OPEN;
+ iop->sem = sema;
+ rtems_libio_iop_freelist = next;
+ goto done;
+ }
+
+failed:
+ iop = 0;
+
+done:
+ rtems_libio_unlock();
+ return iop;
+}
+
+/*
+ * rtems_libio_free
+ *
+ * This routine frees the resources associated with an IOP (file descriptor)
+ * and clears the slot in the IOP Table.
+ */
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_lock();
+
+ if (iop->sem)
+ rtems_semaphore_delete(iop->sem);
+
+ iop->flags &= ~LIBIO_FLAGS_OPEN;
+ iop->data1 = rtems_libio_iop_freelist;
+ rtems_libio_iop_freelist = iop;
+
+ rtems_libio_unlock();
+}
+
+/*
+ * 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 at least 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.
+ */
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t * fs_mt_entry
+)
+{
+ rtems_libio_t *iop;
+ int result = 0;
+ uint32_t i;
+
+ rtems_libio_lock();
+
+ /*
+ * Look for any active file descriptor entry.
+ */
+
+ for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
+
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
+
+ if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ rtems_libio_unlock();
+
+ return result;
+}
+
+/*
+ * 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.
+ */
+
+int rtems_libio_is_file_open(
+ void *node_access
+)
+{
+ rtems_libio_t *iop;
+ int result=0;
+ uint32_t i;
+
+ rtems_libio_lock();
+
+ /*
+ * Look for any active file descriptor entry.
+ */
+
+ for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
+
+ if ( iop->pathinfo.node_access == node_access ) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ rtems_libio_unlock();
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/libio_init.c b/cpukit/libcsupport/src/libio_init.c
new file mode 100644
index 0000000000..a6b99870a5
--- /dev/null
+++ b/cpukit/libcsupport/src/libio_init.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h> /* libio_.h pulls in rtems */
+#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 <errno.h>
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include <rtems/libio.h> /* libio.h not pulled in by rtems */
+
+/*
+ * File descriptor Table Information
+ */
+
+rtems_id rtems_libio_semaphore;
+rtems_libio_t *rtems_libio_iops;
+rtems_libio_t *rtems_libio_iop_freelist;
+
+/*
+ * rtems_libio_init
+ *
+ * Called by BSP startup code to initialize the libio subsystem.
+ */
+
+void rtems_libio_init( void )
+{
+ rtems_status_code rc;
+ uint32_t i;
+ rtems_libio_t *iop;
+
+ 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);
+
+ iop = rtems_libio_iop_freelist = rtems_libio_iops;
+ for (i = 0 ; (i + 1) < rtems_libio_number_iops ; i++, iop++)
+ iop->data1 = iop + 1;
+ iop->data1 = NULL;
+ }
+
+ /*
+ * 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.
+ */
+
+ if (rtems_fs_init_helper)
+ (* rtems_fs_init_helper)();
+}
diff --git a/cpukit/libcsupport/src/libio_sockets.c b/cpukit/libcsupport/src/libio_sockets.c
new file mode 100644
index 0000000000..c67e19d78c
--- /dev/null
+++ b/cpukit/libcsupport/src/libio_sockets.c
@@ -0,0 +1,73 @@
+/*
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the socket calls.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * Convert an RTEMS file descriptor to a BSD socket pointer.
+ */
+
+struct socket *rtems_bsdnet_fdToSocket(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /* same as rtems_libio_check_fd(_fd) but different return */
+ if ((uint32_t)fd >= rtems_libio_number_iops) {
+ errno = EBADF;
+ return NULL;
+ }
+ iop = &rtems_libio_iops[fd];
+
+ /* same as rtems_libio_check_is_open(iop) but different return */
+ if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ if (iop->data1 == NULL)
+ errno = EBADF;
+ return iop->data1;
+}
+
+/*
+ * Create an RTEMS file descriptor for a socket
+ */
+
+int rtems_bsdnet_makeFdForSocket(
+ void *so,
+ const rtems_filesystem_file_handlers_r *h
+)
+{
+ rtems_libio_t *iop;
+ int fd;
+
+ iop = rtems_libio_allocate();
+ if (iop == 0)
+ rtems_set_errno_and_return_minus_one( ENFILE );
+
+ fd = iop - rtems_libio_iops;
+ iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ;
+ iop->data0 = fd;
+ iop->data1 = so;
+ iop->pathinfo.handlers = h;
+ iop->pathinfo.ops = &rtems_filesystem_operations_default;
+ return fd;
+}
diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c
new file mode 100644
index 0000000000..11b6521dea
--- /dev/null
+++ b/cpukit/libcsupport/src/link.c
@@ -0,0 +1,94 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.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, strlen( 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_h)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 ) {
+ rtems_filesystem_freenode( &existing_loc );
+ return -1;
+ }
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry ) {
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_filesystem_freenode( &parent_loc );
+ rtems_set_errno_and_return_minus_one( EXDEV );
+ }
+
+ result = (*parent_loc.ops->link_h)( &existing_loc, &parent_loc, name_start );
+
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_filesystem_freenode( &parent_loc );
+
+ return result;
+}
+
+/*
+ * _link_r
+ *
+ * This is the Newlib dependent reentrant version of link().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _link_r(
+ struct _reent *ptr __attribute__((unused)),
+ const char *existing,
+ const char *new
+)
+{
+ return link( existing, new );
+}
+#endif
diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c
new file mode 100644
index 0000000000..3f37029807
--- /dev/null
+++ b/cpukit/libcsupport/src/lseek.c
@@ -0,0 +1,94 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+ off_t old_offset;
+ off_t status;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the lseek().
+ */
+
+ old_offset = iop->offset;
+ 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:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * At this time, handlers assume iop->offset has the desired
+ * new offset.
+ */
+
+ status = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
+ if ( status == (off_t) -1 )
+ iop->offset = old_offset;
+
+ /*
+ * So if the operation failed, we have to restore iop->offset.
+ */
+
+ return status;
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE__LSEEK_R)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
diff --git a/cpukit/libcsupport/src/lstat.c b/cpukit/libcsupport/src/lstat.c
new file mode 100644
index 0000000000..f034f4aa76
--- /dev/null
+++ b/cpukit/libcsupport/src/lstat.c
@@ -0,0 +1,22 @@
+/*
+ * lstat() - BSD 4.3 and SVR4 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _STAT_NAME lstat
+#define _STAT_R_NAME _lstat_r
+#define _STAT_FOLLOW_LINKS false
+
+#include "stat.c"
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
new file mode 100644
index 0000000000..6bb77a4630
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc.c
@@ -0,0 +1,83 @@
+/*
+ * RTEMS Malloc Family Implementation
+ *
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include <stdlib.h>
+#include <errno.h>
+
+#include "malloc_p.h"
+
+void *malloc(
+ size_t size
+)
+{
+ void *return_this;
+
+ MSBUMP(malloc_calls, 1);
+
+ /*
+ * If some free's have been deferred, then do them now.
+ */
+ malloc_deferred_frees_process();
+
+ /*
+ * Validate the parameters
+ */
+ if ( !size )
+ return (void *) 0;
+
+ /*
+ * Do not attempt to allocate memory if not in correct system state.
+ */
+ if ( _System_state_Is_up(_System_state_Get()) &&
+ !malloc_is_system_state_OK() )
+ return NULL;
+
+ /*
+ * Try to give a segment in the current heap if there is not
+ * enough space then try to grow the heap.
+ * If this fails then return a NULL pointer.
+ */
+
+ return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size );
+
+ if ( !return_this ) {
+ if (rtems_malloc_sbrk_helpers)
+ return_this = (*rtems_malloc_sbrk_helpers->extend)( size );
+ if ( !return_this ) {
+ errno = ENOMEM;
+ return (void *) 0;
+ }
+ }
+
+ /*
+ * If the user wants us to dirty the allocated memory, then do it.
+ */
+ if ( rtems_malloc_dirty_helper )
+ (*rtems_malloc_dirty_helper)( return_this, size );
+
+ /*
+ * If configured, update the statistics
+ */
+ if ( rtems_malloc_statistics_helpers )
+ (*rtems_malloc_statistics_helpers->at_malloc)(return_this);
+
+ return return_this;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/malloc_deferred.c b/cpukit/libcsupport/src/malloc_deferred.c
new file mode 100644
index 0000000000..4289a899bc
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_deferred.c
@@ -0,0 +1,60 @@
+/*
+ * Process free requests deferred because they were from ISR
+ * or other critical section.
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include <stdlib.h>
+#include <errno.h>
+
+#include "malloc_p.h"
+
+rtems_chain_control RTEMS_Malloc_GC_list;
+
+bool malloc_is_system_state_OK(void)
+{
+ if ( _Thread_Dispatch_disable_level > 0 )
+ return false;
+
+ if ( _ISR_Nest_level > 0 )
+ return false;
+
+ return true;
+}
+
+void malloc_deferred_frees_initialize(void)
+{
+ rtems_chain_initialize_empty(&RTEMS_Malloc_GC_list);
+}
+
+void malloc_deferred_frees_process(void)
+{
+ rtems_chain_node *to_be_freed;
+
+ /*
+ * If some free's have been deferred, then do them now.
+ */
+ while ((to_be_freed = rtems_chain_get(&RTEMS_Malloc_GC_list)) != NULL)
+ free(to_be_freed);
+}
+
+void malloc_deferred_free(
+ void *pointer
+)
+{
+ rtems_chain_append(&RTEMS_Malloc_GC_list, (rtems_chain_node *)pointer);
+}
+#endif
diff --git a/cpukit/libcsupport/src/malloc_dirtier.c b/cpukit/libcsupport/src/malloc_dirtier.c
new file mode 100644
index 0000000000..eb6ae7ccf3
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_dirtier.c
@@ -0,0 +1,30 @@
+/*
+ * RTEMS Malloc Family -- Dirty Memory from Malloc
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include "malloc_p.h"
+
+#include <errno.h>
+
+void rtems_malloc_dirty_memory(
+ void *start,
+ size_t size
+)
+{
+ (void) memset(start, 0xCF, size);
+}
diff --git a/cpukit/libcsupport/src/malloc_get_statistics.c b/cpukit/libcsupport/src/malloc_get_statistics.c
new file mode 100644
index 0000000000..c13a1555e8
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_get_statistics.c
@@ -0,0 +1,33 @@
+/*
+ * malloc_get_statistics Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+int malloc_get_statistics(
+ rtems_malloc_statistics_t *stats
+)
+{
+ if ( !stats )
+ return -1;
+ _RTEMS_Lock_allocator();
+ *stats = rtems_malloc_statistics;
+ _RTEMS_Unlock_allocator();
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/malloc_initialize.c b/cpukit/libcsupport/src/malloc_initialize.c
new file mode 100644
index 0000000000..e00a868e5a
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_initialize.c
@@ -0,0 +1,114 @@
+/**
+ * @file
+ *
+ * @brief Malloc initialization implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include <rtems/score/wkspace.h>
+#include "malloc_p.h"
+
+/* FIXME: Dummy function */
+#ifndef RTEMS_NEWLIB
+void RTEMS_Malloc_Initialize(
+ void *heap_begin,
+ uintptr_t heap_size,
+ size_t sbrk_amount
+)
+{
+}
+#else
+rtems_malloc_statistics_t rtems_malloc_statistics;
+extern bool rtems_unified_work_area;
+
+void RTEMS_Malloc_Initialize(
+ void *heap_begin,
+ uintptr_t heap_size,
+ size_t sbrk_amount
+)
+{
+ /*
+ * If configured, initialize the statistics support
+ */
+ if ( rtems_malloc_statistics_helpers != NULL ) {
+ (*rtems_malloc_statistics_helpers->initialize)();
+ }
+
+ /*
+ * Initialize the garbage collection list to start with nothing on it.
+ */
+ malloc_deferred_frees_initialize();
+
+ /*
+ * Initialize the optional sbrk support for extending the heap
+ */
+ if ( rtems_malloc_sbrk_helpers != NULL ) {
+ heap_begin = (*rtems_malloc_sbrk_helpers->initialize)(
+ heap_begin,
+ sbrk_amount
+ );
+ heap_size = (uintptr_t) sbrk_amount;
+ }
+
+ /*
+ * If this system is configured to use the same heap for
+ * the RTEMS Workspace and C Program Heap, then we need to
+ * be very very careful about destroying the initialization
+ * that has already been done.
+ */
+
+ /*
+ * If the BSP is not clearing out the workspace, then it is most likely
+ * not clearing out the initial memory for the heap. There is no
+ * standard supporting zeroing out the heap memory. But much code
+ * with UNIX history seems to assume that memory malloc'ed during
+ * initialization (before any free's) is zero'ed. This is true most
+ * of the time under UNIX because zero'ing memory when it is first
+ * given to a process eliminates the chance of a process seeing data
+ * left over from another process. This would be a security violation.
+ */
+
+ if (
+ !rtems_unified_work_area
+ && rtems_configuration_get_do_zero_of_workspace()
+ ) {
+ memset( heap_begin, 0, heap_size );
+ }
+
+ /*
+ * Unfortunately we cannot use assert if this fails because if this
+ * has failed we do not have a heap and if we do not have a heap
+ * STDIO cannot work because there will be no buffers.
+ */
+
+ if ( !rtems_unified_work_area ) {
+ uintptr_t status = _Protected_heap_Initialize(
+ RTEMS_Malloc_Heap,
+ heap_begin,
+ heap_size,
+ CPU_HEAP_ALIGNMENT
+ );
+ if ( status == 0 ) {
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+ }
+ }
+
+ MSBUMP( space_available, _Protected_heap_Get_size(RTEMS_Malloc_Heap) );
+}
+#endif
diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h
new file mode 100644
index 0000000000..f93f0b9287
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_p.h
@@ -0,0 +1,45 @@
+/*
+ * RTEMS Malloc Family Internal Header
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/protectedheap.h>
+#include <rtems/malloc.h>
+
+#ifdef RTEMS_NEWLIB
+#include <sys/reent.h>
+#endif
+
+#include <stdint.h>
+#include <rtems/chain.h>
+
+/*
+ * Basic management data
+ */
+extern Heap_Control *RTEMS_Malloc_Heap;
+
+/*
+ * Malloc Statistics Structure
+ */
+extern rtems_malloc_statistics_t rtems_malloc_statistics;
+
+#define MSBUMP(_f,_n) rtems_malloc_statistics._f += (_n)
+
+/*
+ * Process deferred free operations
+ */
+bool malloc_is_system_state_OK(void);
+void malloc_deferred_frees_initialize(void);
+void malloc_deferred_frees_process(void);
+void malloc_deferred_free(void *);
diff --git a/cpukit/libcsupport/src/malloc_report_statistics.c b/cpukit/libcsupport/src/malloc_report_statistics.c
new file mode 100644
index 0000000000..24f5505429
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_report_statistics.c
@@ -0,0 +1,26 @@
+/*
+ * malloc_report_statistics Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+void malloc_report_statistics(void)
+{
+ malloc_report_statistics_with_plugin( NULL, printk_plugin );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/malloc_report_statistics_plugin.c b/cpukit/libcsupport/src/malloc_report_statistics_plugin.c
new file mode 100644
index 0000000000..637587190a
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_report_statistics_plugin.c
@@ -0,0 +1,61 @@
+/*
+ * malloc_report_statistics with plugin Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+#include "inttypes.h"
+
+void malloc_report_statistics_with_plugin(
+ void *context,
+ rtems_printk_plugin_t print
+)
+{
+ rtems_malloc_statistics_t *s;
+ uintmax_t allocated;
+
+ s = &rtems_malloc_statistics;
+
+ allocated = s->lifetime_allocated - s->lifetime_freed;
+
+ (*print)(
+ context,
+ "Malloc statistics\n"
+ " avail:%"PRIu32"k allocated:%"PRIu32"k (%"PRId32"%%) "
+ "max:%"PRIu32"k (%"PRIu32"%%)"
+ " lifetime:%"PRIu32"k freed:%"PRIu32"k\n",
+ s->space_available / 1024,
+ allocated / 1024,
+ /* avoid float! */
+ (allocated * 100) / s->space_available,
+ s->max_depth / 1024,
+ (s->max_depth * 100) / s->space_available,
+ (uint32_t) (s->lifetime_allocated / 1024),
+ (uint32_t) (s->lifetime_freed / 1024)
+ );
+ (*print)(
+ context,
+ " Call counts: malloc:%"PRIu32" memalign:%"PRIu32" free:%"PRIu32
+ " realloc:%"PRIu32" calloc:%"PRIu32"\n",
+ s->malloc_calls,
+ s->memalign_calls,
+ s->free_calls,
+ s->realloc_calls,
+ s->calloc_calls
+ );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/malloc_sbrk_helpers.c b/cpukit/libcsupport/src/malloc_sbrk_helpers.c
new file mode 100644
index 0000000000..e917fd36af
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_sbrk_helpers.c
@@ -0,0 +1,112 @@
+/*
+ * RTEMS Malloc -- SBRK Support Plugin
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h> /* sbrk */
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include "malloc_p.h"
+
+#include <errno.h>
+
+size_t RTEMS_Malloc_Sbrk_amount;
+
+void *malloc_sbrk_initialize(
+ void *starting_address,
+ size_t length
+)
+{
+ uintptr_t old_address;
+ uintptr_t uaddress;
+
+ RTEMS_Malloc_Sbrk_amount = length;
+
+ /*
+ * If the starting address is 0 then we are to attempt to
+ * get length worth of memory using sbrk. Make sure we
+ * align the address that we get back.
+ */
+
+ if (!starting_address) {
+ uaddress = (uintptr_t)sbrk(length);
+
+ if (uaddress == (uintptr_t) -1) {
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+ /* DOES NOT RETURN!!! */
+ }
+
+ if (uaddress & (CPU_HEAP_ALIGNMENT-1)) {
+ old_address = uaddress;
+ uaddress = (uaddress + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);
+
+ /*
+ * adjust the length by whatever we aligned by
+ */
+ length -= uaddress - old_address;
+ }
+
+ starting_address = (void *)uaddress;
+ }
+ return starting_address;
+}
+
+void *malloc_sbrk_extend_and_allocate(
+ size_t size
+)
+{
+ uint32_t sbrk_amount;
+ void *starting_address;
+ uint32_t the_size;
+ void *return_this;
+
+ /*
+ * Round to the "requested sbrk amount" so hopefully we won't have
+ * to grow again for a while. This effectively does sbrk() calls
+ * in "page" amounts.
+ */
+
+ sbrk_amount = RTEMS_Malloc_Sbrk_amount;
+
+ if ( sbrk_amount == 0 )
+ return (void *) 0;
+
+ the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
+
+ starting_address = (void *) sbrk(the_size);
+ if ( starting_address == (void*) -1 )
+ return (void *) 0;
+
+ if ( !_Protected_heap_Extend(
+ RTEMS_Malloc_Heap, starting_address, the_size) ) {
+ sbrk(-the_size);
+ errno = ENOMEM;
+ return (void *) 0;
+ }
+
+ MSBUMP(space_available, the_size);
+
+ return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size );
+ return return_this;
+}
+
+
+rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table = {
+ malloc_sbrk_initialize,
+ malloc_sbrk_extend_and_allocate
+};
+
+
diff --git a/cpukit/libcsupport/src/malloc_statistics_helpers.c b/cpukit/libcsupport/src/malloc_statistics_helpers.c
new file mode 100644
index 0000000000..fcd9a5cbde
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_statistics_helpers.c
@@ -0,0 +1,75 @@
+
+/*
+ * _calloc_r Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+#include <sys/reent.h>
+#include <stdlib.h>
+
+
+static void rtems_malloc_statistics_initialize( void )
+{
+ /*
+ * Zero all the statistics
+ */
+ (void) memset(&rtems_malloc_statistics, 0, sizeof(rtems_malloc_statistics));
+}
+
+static void rtems_malloc_statistics_at_malloc(
+ void *pointer
+)
+{
+ uintptr_t actual_size = 0;
+ uint32_t current_depth;
+ rtems_malloc_statistics_t *s = &rtems_malloc_statistics;
+
+ if ( !pointer )
+ return;
+
+ _Protected_heap_Get_block_size(RTEMS_Malloc_Heap, pointer, &actual_size);
+
+ MSBUMP(lifetime_allocated, actual_size);
+
+ current_depth = (uint32_t) (s->lifetime_allocated - s->lifetime_freed);
+ if (current_depth > s->max_depth)
+ s->max_depth = current_depth;
+}
+
+/*
+ * If the pointer is not in the heap, then we won't be able to get its
+ * size and thus we skip updating the statistics.
+ */
+static void rtems_malloc_statistics_at_free(
+ void *pointer
+)
+{
+ uintptr_t size;
+
+ if (_Protected_heap_Get_block_size(RTEMS_Malloc_Heap, pointer, &size) ) {
+ MSBUMP(lifetime_freed, size);
+ }
+}
+
+rtems_malloc_statistics_functions_t rtems_malloc_statistics_helpers_table = {
+ rtems_malloc_statistics_initialize,
+ rtems_malloc_statistics_at_malloc,
+ rtems_malloc_statistics_at_free,
+};
+
+#endif
diff --git a/cpukit/libcsupport/src/malloc_walk.c b/cpukit/libcsupport/src/malloc_walk.c
new file mode 100644
index 0000000000..6b6602b2ff
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc_walk.c
@@ -0,0 +1,28 @@
+/*
+ * malloc_walk Implementation
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+#include <stdlib.h>
+
+void malloc_walk(size_t source, size_t printf_enabled)
+{
+ _Protected_heap_Walk( RTEMS_Malloc_Heap, (int) source, printf_enabled );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/mallocfreespace.c b/cpukit/libcsupport/src/mallocfreespace.c
new file mode 100644
index 0000000000..cb0eb1f2ea
--- /dev/null
+++ b/cpukit/libcsupport/src/mallocfreespace.c
@@ -0,0 +1,42 @@
+/*
+ * RTEMS Malloc Get Free Information
+ *
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/protectedheap.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#include "malloc_p.h"
+
+/*
+ * Find amount of free heap remaining
+ */
+
+size_t malloc_free_space( void )
+{
+ Heap_Information info;
+
+ _Protected_heap_Get_free_information( RTEMS_Malloc_Heap, &info );
+ return (size_t) info.largest;
+}
diff --git a/cpukit/libcsupport/src/mallocgetheapptr.c b/cpukit/libcsupport/src/mallocgetheapptr.c
new file mode 100644
index 0000000000..b0df2f57fb
--- /dev/null
+++ b/cpukit/libcsupport/src/mallocgetheapptr.c
@@ -0,0 +1,26 @@
+/*
+ * RTEMS Malloc Get Heap Pointer -- Primarily for Debug
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include "malloc_p.h"
+
+Heap_Control *malloc_get_heap_pointer( void )
+{
+ return RTEMS_Malloc_Heap;
+}
diff --git a/cpukit/libcsupport/src/mallocinfo.c b/cpukit/libcsupport/src/mallocinfo.c
new file mode 100644
index 0000000000..d1c3266aeb
--- /dev/null
+++ b/cpukit/libcsupport/src/mallocinfo.c
@@ -0,0 +1,39 @@
+/*
+ * RTEMS Malloc Get Status Information
+ *
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/protectedheap.h>
+
+extern Heap_Control *RTEMS_Malloc_Heap;
+
+/*
+ * Find amount of free heap remaining
+ */
+
+int malloc_info(
+ Heap_Information_block *the_info
+)
+{
+ if ( !the_info )
+ return -1;
+
+ _Protected_heap_Get_information( RTEMS_Malloc_Heap, the_info );
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/mallocsetheapptr.c b/cpukit/libcsupport/src/mallocsetheapptr.c
new file mode 100644
index 0000000000..e0d1471750
--- /dev/null
+++ b/cpukit/libcsupport/src/mallocsetheapptr.c
@@ -0,0 +1,28 @@
+/*
+ * RTEMS Malloc Set Heap Pointer -- Primarily for Debug
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include "malloc_p.h"
+
+void malloc_set_heap_pointer(
+ Heap_Control *new_heap
+)
+{
+ RTEMS_Malloc_Heap = new_heap;
+}
diff --git a/cpukit/libcsupport/src/mkdir.c b/cpukit/libcsupport/src/mkdir.c
new file mode 100644
index 0000000000..2fae8a733a
--- /dev/null
+++ b/cpukit/libcsupport/src/mkdir.c
@@ -0,0 +1,30 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/mkfifo.c b/cpukit/libcsupport/src/mkfifo.c
new file mode 100644
index 0000000000..efe6207bf8
--- /dev/null
+++ b/cpukit/libcsupport/src/mkfifo.c
@@ -0,0 +1,28 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c
new file mode 100644
index 0000000000..29aff43c31
--- /dev/null
+++ b/cpukit/libcsupport/src/mknod.c
@@ -0,0 +1,73 @@
+/*
+ * 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-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.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;
+
+ /*
+ * The file type is field within the mode. Check we have a sane mode set.
+ */
+ switch (mode & S_IFMT)
+ {
+ case S_IFDIR:
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFREG:
+ case S_IFIFO:
+ break;
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ result = (*temp_loc.ops->evalformake_h)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
+
+ rtems_filesystem_freenode( &temp_loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/mount-mgr.c b/cpukit/libcsupport/src/mount-mgr.c
new file mode 100644
index 0000000000..c610ff6998
--- /dev/null
+++ b/cpukit/libcsupport/src/mount-mgr.c
@@ -0,0 +1,169 @@
+/*
+ * mount()
+ *
+ * Mange the mount table. You can iterate on mounts and file systems, as well
+ * as add and remove file systems not in the file system confiration table.
+ *
+ * COPYRIGHT (c) Chris Johns <chrisj@rtems.org> 2010.
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rtems/chain.h>
+#include <rtems/seterr.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+
+typedef struct {
+ rtems_chain_node node;
+ rtems_filesystem_table_t entry;
+} filesystem_node;
+
+static RTEMS_CHAIN_DEFINE_EMPTY(filesystem_chain);
+
+bool rtems_filesystem_iterate(
+ rtems_per_filesystem_routine routine,
+ void *routine_arg
+)
+{
+ const rtems_filesystem_table_t *table_entry = &rtems_filesystem_table [0];
+ rtems_chain_node *node = NULL;
+ bool stop = false;
+
+ while ( table_entry->type && !stop ) {
+ stop = (*routine)( table_entry, routine_arg );
+ ++table_entry;
+ }
+
+ if ( !stop ) {
+ rtems_libio_lock();
+ for (
+ node = rtems_chain_first( &filesystem_chain );
+ !rtems_chain_is_tail( &filesystem_chain, node ) && !stop;
+ node = rtems_chain_next( node )
+ ) {
+ const filesystem_node *fsn = (filesystem_node *) node;
+
+ stop = (*routine)( &fsn->entry, routine_arg );
+ }
+ rtems_libio_unlock();
+ }
+
+ return stop;
+}
+
+typedef struct {
+ const char *type;
+ rtems_filesystem_fsmount_me_t mount_h;
+} find_arg;
+
+static bool find_handler(const rtems_filesystem_table_t *entry, void *arg)
+{
+ find_arg *fa = arg;
+
+ if ( strcmp( entry->type, fa->type ) != 0 ) {
+ return false;
+ } else {
+ fa->mount_h = entry->mount_h;
+
+ return true;
+ }
+}
+
+rtems_filesystem_fsmount_me_t
+rtems_filesystem_get_mount_handler(
+ const char *type
+)
+{
+ find_arg fa = {
+ .type = type,
+ .mount_h = NULL
+ };
+
+ if ( type != NULL ) {
+ rtems_filesystem_iterate( find_handler, &fa );
+ }
+
+ return fa.mount_h;
+}
+
+int
+rtems_filesystem_register(
+ const char *type,
+ rtems_filesystem_fsmount_me_t mount_h
+)
+{
+ size_t type_size = strlen(type) + 1;
+ size_t fsn_size = sizeof( filesystem_node ) + type_size;
+ filesystem_node *fsn = malloc( fsn_size );
+ char *type_storage = (char *) fsn + sizeof( *fsn );
+
+ if ( fsn == NULL )
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ memcpy(type_storage, type, type_size);
+ fsn->entry.type = type_storage;
+ fsn->entry.mount_h = mount_h;
+
+ rtems_libio_lock();
+ if ( rtems_filesystem_get_mount_handler( type ) == NULL ) {
+ rtems_chain_append( &filesystem_chain, &fsn->node );
+ } else {
+ rtems_libio_unlock();
+ free( fsn );
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+ rtems_libio_unlock();
+
+ return 0;
+}
+
+int
+rtems_filesystem_unregister(
+ const char *type
+)
+{
+ rtems_chain_node *node = NULL;
+
+ if ( type == NULL ) {
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ rtems_libio_lock();
+ for (
+ node = rtems_chain_first( &filesystem_chain );
+ !rtems_chain_is_tail( &filesystem_chain, node );
+ node = rtems_chain_next( node )
+ ) {
+ filesystem_node *fsn = (filesystem_node *) node;
+
+ if ( strcmp( fsn->entry.type, type ) == 0 ) {
+ rtems_chain_extract( node );
+ free( fsn );
+ rtems_libio_unlock();
+
+ return 0;
+ }
+ }
+ rtems_libio_unlock();
+
+ rtems_set_errno_and_return_minus_one( ENOENT );
+}
diff --git a/cpukit/libcsupport/src/mount-mktgt.c b/cpukit/libcsupport/src/mount-mktgt.c
new file mode 100644
index 0000000000..3b4d50aded
--- /dev/null
+++ b/cpukit/libcsupport/src/mount-mktgt.c
@@ -0,0 +1,56 @@
+/**
+ * @file
+ *
+ * @ingroup LibIO
+ *
+ * @brief mount_and_make_target_path() implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio.h>
+
+int mount_and_make_target_path(
+ const char *source,
+ const char *target,
+ const char *filesystemtype,
+ rtems_filesystem_options_t options,
+ const void *data
+)
+{
+ int rv = -1;
+
+ if (target != NULL) {
+ rv = rtems_mkdir(target, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (rv == 0) {
+ rv = mount(
+ source,
+ target,
+ filesystemtype,
+ options,
+ data
+ );
+ }
+ } else {
+ errno = EINVAL;
+ }
+
+ return rv;
+}
diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c
new file mode 100644
index 0000000000..00a07aab3a
--- /dev/null
+++ b/cpukit/libcsupport/src/mount.c
@@ -0,0 +1,282 @@
+/*
+ * 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-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rtems/chain.h>
+#include <rtems/seterr.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+
+static RTEMS_CHAIN_DEFINE_EMPTY(mount_chain);
+
+/*
+ * Default pathconfs.
+ */
+const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf = {
+ 5, /* link_max: count */
+ 128, /* max_canon: max formatted input line size */
+ 7, /* max_input: max input line size */
+ 255, /* name_max: max name */
+ 255, /* path_max: max path */
+ 1024, /* pipe_buf: pipe buffer size */
+ 0, /* posix_async_io: async IO supported on fs, 0=no, 1=yes */
+ 0 , /* posix_chown_restrictions: can chown: 0=no, 1=yes */
+ 1, /* posix_no_trunc: error on filenames > max name, 0=no, 1=yes */
+ 0, /* posix_prio_io: priority IO, 0=no, 1=yes */
+ 0, /* posix_sync_io: file can be sync'ed, 0=no, 1=yes */
+ 0 /* posix_vdisable: special char processing, 0=no, 1=yes */
+};
+
+static bool is_node_fs_root(
+ const rtems_filesystem_mount_table_entry_t *mt_entry,
+ void *arg
+)
+{
+ return arg == mt_entry->mt_fs_root.node_access;
+}
+
+static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
+ const char *source_or_null,
+ const char *target_or_null,
+ const char *filesystemtype,
+ size_t *target_length_ptr
+)
+{
+ const char *target = target_or_null != NULL ? target_or_null : "/";
+ size_t filesystemtype_size = strlen( filesystemtype ) + 1;
+ size_t source_size = source_or_null != NULL ?
+ strlen( source_or_null ) + 1 : 0;
+ size_t target_size = strlen( target ) + 1;
+ size_t size = sizeof( rtems_filesystem_mount_table_entry_t )
+ + filesystemtype_size + source_size + target_size;
+ rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size );
+
+ if ( mt_entry != NULL ) {
+ char *str = (char *) mt_entry + sizeof( *mt_entry );
+
+ memcpy( str, filesystemtype, filesystemtype_size );
+ mt_entry->type = str;
+ str += filesystemtype_size;
+
+ memcpy( str, source_or_null, source_size );
+ mt_entry->dev = str;
+ str += source_size;
+
+ memcpy( str, target, target_size );
+ mt_entry->target = str;
+ }
+
+ *target_length_ptr = target_size - 1;
+
+ return mt_entry;
+}
+
+/*
+ * 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(
+ const char *source,
+ const char *target,
+ const char *filesystemtype,
+ rtems_filesystem_options_t options,
+ const void *data
+)
+{
+ rtems_filesystem_fsmount_me_t mount_h = NULL;
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_mount_table_entry_t *mt_entry = NULL;
+ rtems_filesystem_location_info_t *loc_to_free = NULL;
+ bool has_target = target != NULL;
+ size_t target_length = 0;
+
+ /*
+ * Are the file system options valid?
+ */
+
+ if ( options != RTEMS_FILESYSTEM_READ_ONLY &&
+ options != RTEMS_FILESYSTEM_READ_WRITE )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Get mount handler
+ */
+ mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
+ if ( !mount_h )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Allocate a mount table entry
+ */
+ mt_entry = alloc_mount_table_entry(
+ source,
+ target,
+ filesystemtype,
+ &target_length
+ );
+ if ( !mt_entry )
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ mt_entry->mt_fs_root.mt_entry = mt_entry;
+ mt_entry->options = options;
+ mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( has_target ) {
+ if ( rtems_filesystem_evaluate_path(
+ target, target_length, RTEMS_LIBIO_PERMS_RWX, &loc, true ) == -1 )
+ goto cleanup_and_bail;
+
+ loc_to_free = &loc;
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( rtems_filesystem_mount_iterate( is_node_fs_root, loc.node_access ) ) {
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry. Note: the information that
+ * may have been allocated in loc should not be sent to freenode
+ * until the system is unmounted. It may be needed to correctly
+ * traverse the tree.
+ */
+
+ mt_entry->mt_point_node.node_access = loc.node_access;
+ mt_entry->mt_point_node.handlers = loc.handlers;
+ mt_entry->mt_point_node.ops = loc.ops;
+ mt_entry->mt_point_node.mt_entry = loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( loc.ops->mount_h( mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ } else {
+ /*
+ * Do we already have a base file system ?
+ */
+ if ( !rtems_chain_is_empty( &mount_chain ) ) {
+ errno = EINVAL;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be left to null to indicate that this
+ * is the root of the entire file system.
+ */
+ }
+
+ if ( (*mount_h)( mt_entry, data ) ) {
+ /*
+ * Try to undo the mount operation
+ */
+ loc.ops->unmount_h( mt_entry );
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+ rtems_libio_lock();
+ rtems_chain_append( &mount_chain, &mt_entry->Node );
+ rtems_libio_unlock();
+
+ if ( !has_target )
+ rtems_filesystem_root = mt_entry->mt_fs_root;
+
+ return 0;
+
+cleanup_and_bail:
+
+ free( mt_entry );
+
+ if ( loc_to_free )
+ rtems_filesystem_freenode( loc_to_free );
+
+ return -1;
+}
+
+bool rtems_filesystem_mount_iterate(
+ rtems_per_filesystem_mount_routine routine,
+ void *routine_arg
+)
+{
+ rtems_chain_node *node = NULL;
+ bool stop = false;
+
+ rtems_libio_lock();
+ for (
+ node = rtems_chain_first( &mount_chain );
+ !rtems_chain_is_tail( &mount_chain, node ) && !stop;
+ node = rtems_chain_next( node )
+ ) {
+ const rtems_filesystem_mount_table_entry_t *mt_entry =
+ (rtems_filesystem_mount_table_entry_t *) node;
+
+ stop = (*routine)( mt_entry, routine_arg );
+ }
+ rtems_libio_unlock();
+
+ return stop;
+}
diff --git a/cpukit/libcsupport/src/newlibc_exit.c b/cpukit/libcsupport/src/newlibc_exit.c
new file mode 100644
index 0000000000..818ba884f4
--- /dev/null
+++ b/cpukit/libcsupport/src/newlibc_exit.c
@@ -0,0 +1,160 @@
+/*
+ * 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.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#if defined(RTEMS_NEWLIB)
+#include <rtems/libcsupport.h>
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+
+#include <stdlib.h> /* for free() */
+#include <string.h> /* for memset() */
+
+#include <sys/reent.h> /* for extern of _REENT (aka _impure_ptr) */
+#include <errno.h>
+
+#include <stdio.h>
+
+int _fwalk(struct _reent *ptr, int (*function) (FILE *) );
+
+/* do we think we are reentrant? */
+extern int libc_reentrant;
+extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+
+/*
+ * CYGNUS newlib routine that does atexit() processing and flushes
+ * stdio streams
+ * undocumented
+ */
+
+extern void _wrapup_reent(struct _reent *);
+extern void _reclaim_reent(struct _reent *);
+
+void libc_wrapup(void)
+{
+ /*
+ * In case RTEMS is already down, don't do this. It could be
+ * dangerous.
+ */
+
+ if (!_System_state_Is_up(_System_state_Get()))
+ return;
+
+ /*
+ * This was already done if the user called exit() directly .
+ _wrapup_reent(0);
+ */
+
+ if (_REENT != _global_impure_ptr) {
+ _wrapup_reent(_global_impure_ptr);
+#if 0
+ /* Don't reclaim this one, just in case we do printfs
+ * on the way out to ROM.
+ */
+ _reclaim_reent(&libc_global_reent);
+#endif
+ _REENT = _global_impure_ptr;
+ }
+
+ /*
+ * Try to drain output buffers.
+ *
+ * Should this be changed to do *all* file streams?
+ * _fwalk (_REENT, fclose);
+ */
+
+ fclose (stdin);
+ fclose (stdout);
+ fclose (stderr);
+}
+
+/*
+ * Function: _exit
+ * Created: 94/12/10
+ *
+ * Description:
+ * Called from exit() after it does atexit() processing and stdio fflush's
+ *
+ * called from bottom of exit() to really delete the task.
+ * If we are using reentrant libc, then let the delete extension
+ * do all the work, otherwise if a shutdown is in progress,
+ * then just do it.
+ *
+ * Parameters:
+ * exit status
+ *
+ * Returns:
+ * does not return
+ *
+ * Side Effects:
+ *
+ * Notes:
+ *
+ *
+ * Deficiencies/ToDo:
+ *
+ *
+ */
+
+#include <unistd.h>
+
+/* FIXME: These defines are a blatant hack */
+ #define EXIT_SYMBOL _exit
+
+ #if defined(__AVR__)
+ #undef __USE_INIT_FINI__
+ #endif
+ #if defined(__USE_INIT_FINI__)
+ #if defined(__m32r__)
+ #define FINI_SYMBOL __fini
+ #else
+ #define FINI_SYMBOL _fini
+ #endif
+
+ extern void FINI_SYMBOL( void );
+ #endif
+
+void EXIT_SYMBOL(int status)
+{
+ /*
+ * If the toolset uses init/fini sections, then we need to
+ * run the global destructors now.
+ */
+ #if defined(__USE_INIT_FINI__)
+ FINI_SYMBOL();
+ #endif
+
+ /*
+ * We need to do the exit processing on the global reentrancy structure.
+ * This has already been done on the per task reentrancy structure
+ * associated with this task.
+ */
+
+ libc_wrapup();
+ rtems_shutdown_executive(status);
+ for (;;) ; /* to avoid warnings */
+}
+
+
+#endif
diff --git a/cpukit/libcsupport/src/newlibc_init.c b/cpukit/libcsupport/src/newlibc_init.c
new file mode 100644
index 0000000000..4d2cef5405
--- /dev/null
+++ b/cpukit/libcsupport/src/newlibc_init.c
@@ -0,0 +1,41 @@
+/*
+ * 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.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB)
+
+/*
+ * Init libc for CYGNUS newlib
+ *
+ * Set up _REENT to use our global libc_global_reent.
+ * (newlib provides a global of its own, but we prefer our own name for it)
+ *
+ * If reentrancy is desired (which it should be), then
+ * we install the task extension hooks to maintain the
+ * newlib reentrancy global variable _REENT on task
+ * create, delete, switch, exit, etc.
+ *
+ */
+
+
+void
+libc_init(void)
+{
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/newlibc_reent.c b/cpukit/libcsupport/src/newlibc_reent.c
new file mode 100644
index 0000000000..1315dc35dc
--- /dev/null
+++ b/cpukit/libcsupport/src/newlibc_reent.c
@@ -0,0 +1,170 @@
+/*
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#if defined(RTEMS_NEWLIB)
+#include <rtems/libcsupport.h>
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+
+#include <stdlib.h> /* for free() */
+#include <string.h> /* for memset() */
+
+#include <sys/reent.h> /* for extern of _REENT (aka _impure_ptr) */
+#include <errno.h>
+
+/*
+ * NOTE:
+ * There is some problem with doing this on the hpux version
+ * of the UNIX simulator (symptom is printf core dumps), so
+ * we just don't for now.
+ * Not sure if this is a problem with hpux, newlib, or something else.
+ */
+
+#include <stdio.h>
+
+int _fwalk(struct _reent *ptr, int (*function) (FILE *) );
+
+extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+/*
+ * reent struct allocation moved here from libc_start_hook() to avoid
+ * mutual exclusion problems when memory is allocated from the start hook.
+ *
+ * Memory is also now allocated from the workspace rather than the heap.
+ * -- ptorre 9/30/03
+ */
+bool newlib_create_hook(
+ rtems_tcb *current_task __attribute__((unused)),
+ rtems_tcb *creating_task
+)
+{
+ struct _reent *ptr;
+
+ if (_Thread_libc_reent == 0)
+ {
+ _REENT = _global_impure_ptr;
+
+ _Thread_Set_libc_reent (&_REENT);
+ }
+
+ /* NOTE: The RTEMS malloc is reentrant without a reent ptr since
+ * it is based on the Classic API Region Manager.
+ */
+
+ #define REENT_MALLOCED 0
+ #if REENT_MALLOCED
+ ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
+ #else
+ /* It is OK to allocate from the workspace because these
+ * hooks run with thread dispatching disabled.
+ */
+ ptr = (struct _reent *) _Workspace_Allocate(sizeof(struct _reent));
+ #endif
+
+ if (ptr) {
+ _REENT_INIT_PTR((ptr)); /* GCC extension: structure constants */
+ creating_task->libc_reent = ptr;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
+ */
+
+#ifdef NEED_SETVBUF
+void newlib_begin_hook(rtems_tcb *current_task)
+{
+ setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
+}
+#endif
+
+/*
+ * Called when a task is deleted.
+ * Must restore the new lib reentrancy state for the new current
+ * task.
+ *
+ */
+
+int newlib_free_buffers(
+ FILE *fp
+)
+{
+ switch ( fileno(fp) ) {
+ case 0:
+ case 1:
+ case 2:
+ if (fp->_flags & __SMBF) {
+ free( fp->_bf._base );
+ fp->_flags &= ~__SMBF;
+ fp->_bf._base = fp->_p = (unsigned char *) NULL;
+ }
+ break;
+ default:
+ fclose(fp);
+ }
+ return 0;
+}
+
+void newlib_delete_hook(
+ rtems_tcb *current_task,
+ rtems_tcb *deleted_task
+)
+{
+ struct _reent *ptr;
+
+ /*
+ * The reentrancy structure was allocated by newlib using malloc()
+ */
+
+ if (current_task == deleted_task) {
+ ptr = _REENT;
+ } else {
+ ptr = deleted_task->libc_reent;
+ }
+
+ if (ptr && ptr != _global_impure_ptr) {
+/*
+ _wrapup_reent(ptr);
+ _reclaim_reent(ptr);
+*/
+ /*
+ * Just in case there are some buffers lying around.
+ */
+ _fwalk(ptr, newlib_free_buffers);
+#if REENT_MALLOCED
+ free(ptr);
+#else
+ _Workspace_Free(ptr);
+#endif
+ }
+
+ deleted_task->libc_reent = NULL;
+
+ /*
+ * Require the switch back to another task to install its own
+ */
+
+ if ( current_task == deleted_task ) {
+ _REENT = 0;
+ }
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c
new file mode 100644
index 0000000000..a49ebfec0d
--- /dev/null
+++ b/cpukit/libcsupport/src/open.c
@@ -0,0 +1,215 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.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 either 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 loc;
+ rtems_filesystem_location_info_t *loc_to_free = NULL;
+ 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, strlen( pathname ), eval_flags, &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;
+ }
+
+ /*
+ * After we do the mknod(), we have to evaluate the path to get the
+ * "loc" structure needed to actually have the file itself open.
+ * So we created it, and then we need to have "look it up."
+ */
+ status = rtems_filesystem_evaluate_path(
+ pathname, strlen( pathname ), 0x0, &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;
+ loc_to_free = &loc;
+ goto done;
+ }
+
+ loc_to_free = &loc;
+
+ /*
+ * Fill in the file control block based on the loc structure
+ * returned by successful path evaluation.
+ */
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = loc;
+
+ rc = (*iop->pathinfo.handlers->open_h)( iop, pathname, flags, mode );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /*
+ * Optionally truncate the file.
+ */
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ if ( rc ) {
+ if(errno) rc = errno;
+ close( iop - rtems_libio_iops );
+ /* those are released by close(): */
+ iop = 0;
+ loc_to_free = NULL;
+ }
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ if ( loc_to_free )
+ rtems_filesystem_freenode( loc_to_free );
+ rtems_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) && !defined(HAVE__OPEN_R)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr __attribute__((unused)),
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/cpukit/libcsupport/src/open_dev_console.c b/cpukit/libcsupport/src/open_dev_console.c
new file mode 100644
index 0000000000..ce01a9276e
--- /dev/null
+++ b/cpukit/libcsupport/src/open_dev_console.c
@@ -0,0 +1,51 @@
+/*
+ * open_dev_console - open /dev/console
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <fcntl.h>
+
+/*
+ * This is a replaceable stub which opens the console, if present.
+ */
+void open_dev_console(void)
+{
+ int stdin_fd;
+ int stdout_fd;
+ int stderr_fd;
+
+ /*
+ * Attempt to open /dev/console.
+ */
+ if ((stdin_fd = open("/dev/console", O_RDONLY, 0)) == -1) {
+ /*
+ * There may not be a console driver so this is OK.
+ */
+ return;
+ }
+
+ /*
+ * But if we find /dev/console once, we better find it twice more
+ * or something is REALLY wrong.
+ */
+ if ((stdout_fd = open("/dev/console", O_WRONLY, 0)) == -1)
+ rtems_fatal_error_occurred( 0x55544431 ); /* error STD1 */
+
+ if ((stderr_fd = open("/dev/console", O_WRONLY, 0)) == -1)
+ rtems_fatal_error_occurred( 0x55544432 ); /* error STD2 */
+}
+
diff --git a/cpukit/libcsupport/src/pathconf.c b/cpukit/libcsupport/src/pathconf.c
new file mode 100644
index 0000000000..d16f899e95
--- /dev/null
+++ b/cpukit/libcsupport/src/pathconf.c
@@ -0,0 +1,41 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/pipe.c b/cpukit/libcsupport/src/pipe.c
new file mode 100644
index 0000000000..13b2eb5dc6
--- /dev/null
+++ b/cpukit/libcsupport/src/pipe.c
@@ -0,0 +1,32 @@
+/*
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems/seterr.h>
+
+extern int pipe_create(int filsdes[2]);
+
+int pipe(
+ int filsdes[2]
+)
+{
+ if (filsdes == NULL)
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ return pipe_create(filsdes);
+}
diff --git a/cpukit/libcsupport/src/posix_memalign.c b/cpukit/libcsupport/src/posix_memalign.c
new file mode 100644
index 0000000000..cde55f042b
--- /dev/null
+++ b/cpukit/libcsupport/src/posix_memalign.c
@@ -0,0 +1,44 @@
+/*
+ * posix_memalign()
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+int posix_memalign(
+ void **pointer,
+ size_t alignment,
+ size_t size
+)
+{
+ /*
+ * Update call statistics
+ */
+ MSBUMP(memalign_calls, 1);
+
+ if (((alignment - 1) & alignment) != 0 || (alignment < sizeof(void *)))
+ return EINVAL;
+
+ /*
+ * rtems_memalign does all of the error checking work EXCEPT
+ * for adding restrictionso on the alignment.
+ */
+ return rtems_memalign( pointer, alignment, size );
+}
+#endif
diff --git a/cpukit/libcsupport/src/printk.c b/cpukit/libcsupport/src/printk.c
new file mode 100644
index 0000000000..3ac7c8616a
--- /dev/null
+++ b/cpukit/libcsupport/src/printk.c
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 1997 -
+ * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+ *
+ * http://pandora.ist.utl.pt
+ *
+ * Instituto Superior Tecnico * Lisboa * PORTUGAL
+ *
+ * Disclaimer:
+ *
+ * This file is provided "AS IS" without warranty of any kind, either
+ * expressed or implied.
+ *
+ * This code is based on code by: Jose Rufino - IST
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <rtems/bspIo.h>
+
+/*
+ * printk
+ *
+ * Kernel printf function requiring minimal infrastructure.
+ */
+void printk(const char *fmt, ...)
+{
+ va_list ap; /* points to each unnamed argument in turn */
+
+ va_start(ap, fmt); /* make ap point to 1st unnamed arg */
+ vprintk(fmt, ap);
+ va_end(ap); /* clean up when done */
+}
diff --git a/cpukit/libcsupport/src/printk_plugin.c b/cpukit/libcsupport/src/printk_plugin.c
new file mode 100644
index 0000000000..60d93a96af
--- /dev/null
+++ b/cpukit/libcsupport/src/printk_plugin.c
@@ -0,0 +1,34 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <rtems/bspIo.h>
+
+int printk_plugin(
+ void *ignored __attribute__((unused)),
+ const char *format,
+ ...
+)
+{
+ va_list arg_pointer;
+
+ va_start (arg_pointer, format);
+
+ vprintk( format, arg_pointer );
+
+ va_end(arg_pointer); /* clean up when done */
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c
new file mode 100644
index 0000000000..89137200b7
--- /dev/null
+++ b/cpukit/libcsupport/src/privateenv.c
@@ -0,0 +1,204 @@
+/*
+ * Instantiate a private user environment for the calling thread.
+ *
+ * Submitted by: fernando.ruiz@ctv.es (correo@fernando-ruiz.com)
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h> /* free */
+
+#include <rtems.h>
+#include <rtems/chain.h>
+#include <rtems/libio_.h>
+
+/* cleanup a user environment
+ * NOTE: this must be called with
+ * thread dispatching disabled!
+ */
+static void
+free_user_env(void *venv)
+{
+ rtems_user_env_t *env = (rtems_user_env_t*) venv ;
+
+ if (env != &rtems_global_user_env
+ #ifdef HAVE_USERENV_REFCNT
+ && --env->refcnt <= 0
+ #endif
+ ) {
+ rtems_filesystem_freenode( &env->current_directory);
+ rtems_filesystem_freenode( &env->root_directory);
+ free(env);
+ }
+}
+
+rtems_status_code rtems_libio_set_private_env(void)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_id task_id = rtems_task_self();
+ rtems_filesystem_location_info_t root_loc;
+ rtems_filesystem_location_info_t current_loc;
+ rtems_user_env_t *new_env = NULL;
+ int rv = 0;
+
+ rv = rtems_filesystem_evaluate_path("/", 1, 0, &root_loc, 0);
+ if (rv != 0)
+ goto error_0;
+
+ rv = rtems_filesystem_evaluate_path("/", 1, 0, &current_loc, 0);
+ if (rv != 0)
+ goto error_1;
+
+ /*
+ * Malloc is necessary whenever the current task does not
+ * have its own environment in place. This could be:
+ * a) it never had one
+ * OR
+ * b) it shared another task's environment
+ */
+
+ /*
+ * Bharath: I'm not sure if the check can be reduced to
+ * if( rtems_current_user_env->task_id != task_id ) {
+ */
+
+ if (
+ rtems_current_user_env == &rtems_global_user_env
+ || rtems_current_user_env->task_id != task_id
+ ) {
+ new_env = malloc(sizeof(rtems_user_env_t));
+ if (new_env == NULL)
+ goto error_2;
+
+ #ifdef HAVE_USERENV_REFCNT
+ new_env->refcnt = 1;
+ #endif
+
+ sc = rtems_task_variable_add(
+ RTEMS_SELF,
+ (void*)&rtems_current_user_env,
+ (void(*)(void *))free_user_env
+ );
+ if (sc != RTEMS_SUCCESSFUL)
+ goto error_3;
+
+ rtems_current_user_env = new_env;
+ }
+
+ /* Inherit the global values */
+ *rtems_current_user_env = rtems_global_user_env;
+
+ rtems_current_user_env->task_id = task_id;
+
+ /*
+ * Clone the pathlocs. In contrast to most other code we must _not_ free the
+ * original locs because what we are trying to do here is forking off clones.
+ * The reason is a pathloc can be allocated by the file system and needs to
+ * be freed when deleting the environment.
+ */
+ rtems_filesystem_root = root_loc;
+ rtems_filesystem_current = current_loc;
+
+ return RTEMS_SUCCESSFUL;
+
+error_3:
+ free(new_env);
+
+error_2:
+ rtems_filesystem_freenode(&current_loc);
+
+error_1:
+ rtems_filesystem_freenode(&root_loc);
+
+error_0:
+ return RTEMS_NO_MEMORY;
+}
+
+/*
+ * Share the same private environment between two tasks:
+ * Task_id (remote) and RTEMS_SELF(current).
+ */
+
+/* NOTE:
+ *
+ * THIS CODE HAS NO PROTECTION IMPLEMENTED
+ *
+ * Tasks who wish to share their environments must
+ *
+ * a) assert that no participants are concurrently
+ * executing
+ * libio_share_private_env() and/or libio_set_private_env()
+ *
+ * b) mutex access to rtems_filesystem_current, rtems_filesytem_root
+ * while changing any of those (chdir(), chroot()).
+ */
+
+rtems_status_code rtems_libio_share_private_env(rtems_id task_id)
+{
+ rtems_status_code sc;
+ rtems_user_env_t * shared_user_env;
+ rtems_id current_task_id;
+
+ /*
+ * get current task id
+ */
+ current_task_id = rtems_task_self();
+
+ /*
+ * If this was an attempt to share the task with self,
+ * if somebody wanted to do it... Lets tell them, its shared
+ */
+
+ if( task_id == current_task_id )
+ return RTEMS_SUCCESSFUL;
+ /*
+ * Try to get the requested user environment
+ */
+ sc = rtems_task_variable_get(
+ task_id,
+ (void*)&rtems_current_user_env,
+ (void*)&shared_user_env );
+
+ /*
+ * If it was not successful, return the error code
+ */
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ /*
+ * If we are here, we have the required environment to be
+ * shared with the current task
+ */
+
+ /*
+ * If we have a current environment in place, we need to
+ * free it, since we will be sharing the variable with the
+ * shared_user_env
+ */
+
+ if (rtems_current_user_env->task_id==current_task_id) {
+ rtems_user_env_t *tmp = rtems_current_user_env;
+ free_user_env( tmp );
+ }
+
+ /* the current_user_env is the same pointer that remote env */
+ rtems_current_user_env = shared_user_env;
+
+ /* increase the reference count */
+#ifdef HAVE_USERENV_REFCNT
+ rtems_current_user_env->refcnt++;
+#endif
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libcsupport/src/putk.c b/cpukit/libcsupport/src/putk.c
new file mode 100644
index 0000000000..d804cf05e8
--- /dev/null
+++ b/cpukit/libcsupport/src/putk.c
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/bspIo.h>
+
+/*
+ * putk
+ *
+ * Kernel putk (e.g. puts) function requiring minimal infrastrure.
+ */
+void putk(const char *s)
+{
+ const char *p;
+
+ for (p=s ; *p ; p++ )
+ BSP_output_char(*p);
+ BSP_output_char('\n');
+}
diff --git a/cpukit/libcsupport/src/read.c b/cpukit/libcsupport/src/read.c
new file mode 100644
index 0000000000..f4c3bdc322
--- /dev/null
+++ b/cpukit/libcsupport/src/read.c
@@ -0,0 +1,67 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+ssize_t read(
+ int fd,
+ void *buffer,
+ size_t count
+)
+{
+ ssize_t rc;
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open( iop );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ /*
+ * Now process the read().
+ */
+ rc = (*iop->pathinfo.handlers->read_h)( 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) && !defined(HAVE__READ_R)
+
+#include <reent.h>
+
+ssize_t _read_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libcsupport/src/readdir_r.c b/cpukit/libcsupport/src/readdir_r.c
new file mode 100644
index 0000000000..f1d53ae593
--- /dev/null
+++ b/cpukit/libcsupport/src/readdir_r.c
@@ -0,0 +1,30 @@
+/*
+ * readdir_r - reentrant version of readdir()
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_READDIR_R
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+
+/*
+ * The RTEMS version of readdir is already thread-safe.
+ */
+
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
+{
+ *result = readdir(dirp);
+ if (*result)
+ *entry = **result;
+ return *result ? 0 : errno;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/readlink.c b/cpukit/libcsupport/src/readlink.c
new file mode 100644
index 0000000000..1880ed667e
--- /dev/null
+++ b/cpukit/libcsupport/src/readlink.c
@@ -0,0 +1,48 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+ssize_t readlink(
+ const char *pathname,
+ char *buf,
+ size_t bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ if (!buf)
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ result = rtems_filesystem_evaluate_path( pathname, strlen( pathname ),
+ 0, &loc, false );
+ if ( result != 0 )
+ return -1;
+
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ result = (*loc.ops->readlink_h)( &loc, buf, bufsize );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/readv.c b/cpukit/libcsupport/src/readv.c
new file mode 100644
index 0000000000..6b33760504
--- /dev/null
+++ b/cpukit/libcsupport/src/readv.c
@@ -0,0 +1,120 @@
+/*
+ * readv() - POSIX 1003.1 - Read a Vector
+ *
+ * OpenGroup URL:
+ *
+ * http://www.opengroup.org/onlinepubs/009695399/functions/readv.html
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+ssize_t readv(
+ int fd,
+ const struct iovec *iov,
+ int iovcnt
+)
+{
+ ssize_t total;
+ int v;
+ int bytes;
+ rtems_libio_t *iop;
+ bool all_zeros;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open( iop );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ /*
+ * Argument validation on IO vector
+ */
+ if ( !iov )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iovcnt <= 0 )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iovcnt > IOV_MAX )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * OpenGroup says that you are supposed to return EINVAL if the
+ * sum of the iov_len values in the iov array would overflow a
+ * ssize_t.
+ *
+ * Also we would like to ensure that no IO is performed if there
+ * are obvious errors in the iovec. So this extra loop ensures
+ * that we do not do anything if there is an argument error.
+ */
+
+ all_zeros = true;
+ for ( total=0, v=0 ; v < iovcnt ; v++ ) {
+ ssize_t old;
+
+ /*
+ * iov[v].iov_len cannot be less than 0 because size_t is unsigned.
+ * So we only check for zero.
+ */
+ if ( iov[v].iov_base == 0 )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /* check for wrap */
+ old = total;
+ total += iov[v].iov_len;
+ if ( total < old )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iov[v].iov_len )
+ all_zeros = false;
+ }
+
+ /*
+ * A readv with all zeros logically has no effect. Even though
+ * OpenGroup didn't address this case as they did with writev(),
+ * we will handle it the same way for symmetry.
+ */
+ if ( all_zeros == true ) {
+ return 0;
+ }
+
+ /*
+ * Now process the readv().
+ */
+ for ( total=0, v=0 ; v < iovcnt ; v++ ) {
+ bytes = (*iop->pathinfo.handlers->read_h)(
+ iop,
+ iov[v].iov_base,
+ iov[v].iov_len
+ );
+
+ if ( bytes < 0 )
+ return -1;
+
+ if ( bytes > 0 ) {
+ iop->offset += bytes;
+ total += bytes;
+ }
+
+ if (bytes != iov[ v ].iov_len)
+ break;
+ }
+
+ return total;
+}
diff --git a/cpukit/libcsupport/src/realloc.c b/cpukit/libcsupport/src/realloc.c
new file mode 100644
index 0000000000..3689f32e61
--- /dev/null
+++ b/cpukit/libcsupport/src/realloc.c
@@ -0,0 +1,88 @@
+/*
+ * calloc()
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+#include <stdlib.h>
+#include <errno.h>
+
+void *realloc(
+ void *ptr,
+ size_t size
+)
+{
+ uintptr_t old_size;
+ char *new_area;
+
+ MSBUMP(realloc_calls, 1);
+
+ /*
+ * Do not attempt to allocate memory if in a critical section or ISR.
+ */
+
+ if (_System_state_Is_up(_System_state_Get())) {
+ if (_Thread_Dispatch_disable_level > 0)
+ return (void *) 0;
+
+ if (_ISR_Nest_level > 0)
+ return (void *) 0;
+ }
+
+ /*
+ * Continue with realloc().
+ */
+ if ( !ptr )
+ return malloc( size );
+
+ if ( !size ) {
+ free( ptr );
+ return (void *) 0;
+ }
+
+ if ( !_Protected_heap_Get_block_size(RTEMS_Malloc_Heap, ptr, &old_size) ) {
+ errno = EINVAL;
+ return (void *) 0;
+ }
+
+ /*
+ * Now resize it.
+ */
+ if ( _Protected_heap_Resize_block( RTEMS_Malloc_Heap, ptr, size ) ) {
+ return ptr;
+ }
+
+ /*
+ * There used to be a free on this error case but it is wrong to
+ * free the memory per OpenGroup Single UNIX Specification V2
+ * and the C Standard.
+ */
+
+ new_area = malloc( size );
+
+ MSBUMP(malloc_calls, (uint32_t) -1); /* subtract off the malloc */
+
+ if ( !new_area ) {
+ return (void *) 0;
+ }
+
+ memcpy( new_area, ptr, (size < old_size) ? size : old_size );
+ free( ptr );
+
+ return new_area;
+
+}
+#endif
diff --git a/cpukit/libcsupport/src/rmdir.c b/cpukit/libcsupport/src/rmdir.c
new file mode 100644
index 0000000000..d7d4edf675
--- /dev/null
+++ b/cpukit/libcsupport/src/rmdir.c
@@ -0,0 +1,95 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int rmdir(
+ const char *pathname
+)
+{
+ int parentpathlen;
+ const char *name;
+ rtems_filesystem_location_info_t parentloc;
+ rtems_filesystem_location_info_t loc;
+ int i;
+ int result;
+ bool free_parentloc = false;
+
+ /*
+ * Get the parent node of the node we wish to remove. Find the parent path.
+ */
+
+ parentpathlen = rtems_filesystem_dirname ( pathname );
+
+ if ( parentpathlen == 0 )
+ rtems_filesystem_get_start_loc( pathname, &i, &parentloc );
+ else {
+ result = rtems_filesystem_evaluate_path(pathname, parentpathlen,
+ RTEMS_LIBIO_PERMS_WRITE,
+ &parentloc,
+ false );
+ if ( result != 0 )
+ return -1;
+
+ free_parentloc = true;
+ }
+
+ /*
+ * Start from the parent to find the node that should be under it.
+ */
+
+ loc = parentloc;
+ name = pathname + parentpathlen;
+ name += rtems_filesystem_prefix_separators( name, strlen( name ) );
+
+ result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
+ 0, &loc, false );
+ if ( result != 0 ) {
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+ return -1;
+ }
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_freenode( &loc );
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ result = (*loc.handlers->rmnod_h)( &parentloc, &loc );
+
+ rtems_filesystem_freenode( &loc );
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/rtems_heap_extend.c b/cpukit/libcsupport/src/rtems_heap_extend.c
new file mode 100644
index 0000000000..5916852278
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_heap_extend.c
@@ -0,0 +1,45 @@
+/**
+ * @file
+ *
+ * @ingroup libcsupport
+ *
+ * @brief rtems_heap_extend() implementation.
+ */
+
+/*
+ * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+rtems_status_code rtems_heap_extend(
+ void *area_begin,
+ uintptr_t area_size
+)
+{
+ bool ok = _Protected_heap_Extend(RTEMS_Malloc_Heap, area_begin, area_size);
+
+ if (ok) {
+ return RTEMS_SUCCESSFUL;
+ } else {
+ return RTEMS_INVALID_ADDRESS;
+ }
+}
+#endif /* RTEMS_NEWLIB */
diff --git a/cpukit/libcsupport/src/rtems_malloc.c b/cpukit/libcsupport/src/rtems_malloc.c
new file mode 100644
index 0000000000..fcd99438f0
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_malloc.c
@@ -0,0 +1,56 @@
+/**
+ * @file
+ *
+ * @ingroup libcsupport
+ *
+ * @brief rtems_malloc() implementation.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+void *rtems_heap_allocate_aligned_with_boundary(
+ size_t size,
+ uintptr_t alignment,
+ uintptr_t boundary
+)
+{
+ if (
+ _System_state_Is_up( _System_state_Get() )
+ && !malloc_is_system_state_OK()
+ ) {
+ return NULL;
+ }
+
+ malloc_deferred_frees_process();
+
+ /* FIXME: Statistics, boundary checks */
+
+ return _Protected_heap_Allocate_aligned_with_boundary(
+ RTEMS_Malloc_Heap,
+ size,
+ alignment,
+ boundary
+ );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/rtems_memalign.c b/cpukit/libcsupport/src/rtems_memalign.c
new file mode 100644
index 0000000000..2d64cbbfd6
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_memalign.c
@@ -0,0 +1,72 @@
+/*
+ * rtems_memalign() - Raw aligned allocate from Protected Heap
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef RTEMS_NEWLIB
+#include "malloc_p.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+int rtems_memalign(
+ void **pointer,
+ size_t alignment,
+ size_t size
+)
+{
+ void *return_this;
+
+ /*
+ * Parameter error checks
+ */
+ if ( !pointer )
+ return EINVAL;
+
+ *pointer = NULL;
+
+ /*
+ * Do not attempt to allocate memory if not in correct system state.
+ */
+ if ( _System_state_Is_up(_System_state_Get()) &&
+ !malloc_is_system_state_OK() )
+ return EINVAL;
+
+ /*
+ * If some free's have been deferred, then do them now.
+ */
+ malloc_deferred_frees_process();
+
+ /*
+ * Perform the aligned allocation requested
+ */
+ return_this = _Protected_heap_Allocate_aligned(
+ RTEMS_Malloc_Heap,
+ size,
+ alignment
+ );
+ if ( !return_this )
+ return ENOMEM;
+
+ /*
+ * If configured, update the more involved statistics
+ */
+ if ( rtems_malloc_statistics_helpers )
+ (*rtems_malloc_statistics_helpers->at_malloc)(pointer);
+
+ *pointer = return_this;
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/rtems_mkdir.c b/cpukit/libcsupport/src/rtems_mkdir.c
new file mode 100644
index 0000000000..86ef7e1b84
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_mkdir.c
@@ -0,0 +1,141 @@
+/**
+ * @file
+ *
+ * @ingroup LibIO
+ *
+ * @brief rtems_mkdir() implementation.
+ *
+ * The implementation is based on FreeBSD 'bin/mkdir/mkdir.c' revision 163213.
+ */
+
+/*-
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * Copyright (c) 1983, 1992, 1993
+ * The 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.
+ * 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 HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtems/libio.h>
+
+/*
+ * Returns 1 if a directory has been created,
+ * 2 if it already existed, and 0 on failure.
+ */
+static int
+build(char *path, mode_t omode)
+{
+ struct stat sb;
+ mode_t numask, oumask;
+ int first, last, retval;
+ char *p;
+
+ p = path;
+ oumask = 0;
+ retval = 1;
+ if (p[0] == '/') /* Skip leading '/'. */
+ ++p;
+ for (first = 1, last = 0; !last ; ++p) {
+ if (p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if (!last && p[1] == '\0')
+ last = 1;
+ if (first) {
+ /*
+ * POSIX 1003.2:
+ * For each dir operand that does not name an existing
+ * directory, effects equivalent to those caused by the
+ * following command shall occcur:
+ *
+ * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
+ * mkdir [-m mode] dir
+ *
+ * We change the user's umask and then restore it,
+ * instead of doing chmod's.
+ */
+ oumask = umask(0);
+ numask = oumask & ~(S_IWUSR | S_IXUSR);
+ (void)umask(numask);
+ first = 0;
+ }
+ if (last)
+ (void)umask(oumask);
+ if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
+ if (errno == EEXIST || errno == EISDIR) {
+ if (stat(path, &sb) < 0) {
+ retval = 0;
+ break;
+ } else if (!S_ISDIR(sb.st_mode)) {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ retval = 0;
+ break;
+ }
+ if (last)
+ retval = 2;
+ } else {
+ retval = 0;
+ break;
+ }
+ }
+ if (!last)
+ *p = '/';
+ }
+ if (!first && !last)
+ (void)umask(oumask);
+ return (retval);
+}
+
+int
+rtems_mkdir(const char *path, mode_t mode)
+{
+ int success = 0;
+ char *dup_path = strdup(path);
+
+ if (dup_path != NULL) {
+ success = build(dup_path, mode);
+ free(dup_path);
+ }
+
+ return success != 0 ? 0 : -1;
+}
diff --git a/cpukit/libcsupport/src/setegid.c b/cpukit/libcsupport/src/setegid.c
new file mode 100644
index 0000000000..04b93fa070
--- /dev/null
+++ b/cpukit/libcsupport/src/setegid.c
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+
+/*
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+int setegid(
+ gid_t gid
+)
+{
+ _POSIX_types_Egid = gid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/seteuid.c b/cpukit/libcsupport/src/seteuid.c
new file mode 100644
index 0000000000..262641cde3
--- /dev/null
+++ b/cpukit/libcsupport/src/seteuid.c
@@ -0,0 +1,24 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/userenv.h>
+
+int seteuid( uid_t euid )
+{
+ _POSIX_types_Euid = euid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/setgid.c b/cpukit/libcsupport/src/setgid.c
new file mode 100644
index 0000000000..908899cf72
--- /dev/null
+++ b/cpukit/libcsupport/src/setgid.c
@@ -0,0 +1,21 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/userenv.h>
+
+/*
+ *
+ * 4.2.2 Set User and Group IDs, P1003.1b-1993, p. 84
+ */
+int setgid(
+ gid_t gid
+)
+{
+ _POSIX_types_Gid = gid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/setpgid.c b/cpukit/libcsupport/src/setpgid.c
new file mode 100644
index 0000000000..ba8f7afc62
--- /dev/null
+++ b/cpukit/libcsupport/src/setpgid.c
@@ -0,0 +1,24 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.3 Set Process Group ID for Job Control, P1003.1b-1993, p. 89
+ */
+
+int setpgid(
+ pid_t pid __attribute__((unused)),
+ pid_t pgid __attribute__((unused))
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
diff --git a/cpukit/libcsupport/src/setsid.c b/cpukit/libcsupport/src/setsid.c
new file mode 100644
index 0000000000..cbebdb4952
--- /dev/null
+++ b/cpukit/libcsupport/src/setsid.c
@@ -0,0 +1,21 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.2 Create Session and Set Process Group ID, P1003.1b-1993, p. 88
+ */
+
+pid_t setsid( void )
+{
+ rtems_set_errno_and_return_minus_one( EPERM );
+}
diff --git a/cpukit/libcsupport/src/setuid.c b/cpukit/libcsupport/src/setuid.c
new file mode 100644
index 0000000000..0e4234ba09
--- /dev/null
+++ b/cpukit/libcsupport/src/setuid.c
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/userenv.h>
+
+/*
+ *
+ * 4.2.2 Set User and Group IDs, P1003.1b-1993, p. 84
+ */
+int setuid(
+ uid_t uid
+)
+{
+ _POSIX_types_Uid = uid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/stat.c b/cpukit/libcsupport/src/stat.c
new file mode 100644
index 0000000000..9f06deaa52
--- /dev/null
+++ b/cpukit/libcsupport/src/stat.c
@@ -0,0 +1,97 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * Reused from lstat().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * lstat() and stat() share the same implementation with a minor
+ * difference on how links are evaluated.
+ */
+
+#ifndef _STAT_NAME
+#define _STAT_NAME stat
+#define _STAT_R_NAME _stat_r
+#define _STAT_FOLLOW_LINKS true
+#endif
+
+
+#include <rtems.h>
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int _STAT_NAME(
+ 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 )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, strlen( path ),
+ 0, &loc, _STAT_FOLLOW_LINKS );
+ if ( status != 0 )
+ return -1;
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ status = (*loc.handlers->fstat_h)( &loc, buf );
+
+ rtems_filesystem_freenode( &loc );
+
+ return status;
+}
+
+/*
+ * _stat_r, _lstat_r
+ *
+ * This is the Newlib dependent reentrant version of stat() and lstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _STAT_R_NAME(
+ struct _reent *ptr __attribute__((unused)),
+ const char *path,
+ struct stat *buf
+)
+{
+ return _STAT_NAME( path, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/statvfs.c b/cpukit/libcsupport/src/statvfs.c
new file mode 100644
index 0000000000..599aa7edc1
--- /dev/null
+++ b/cpukit/libcsupport/src/statvfs.c
@@ -0,0 +1,52 @@
+/*
+ * COPYRIGHT (c) 2009 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+/*
+ * The statvfs as defined by the SUS:
+ * http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <sys/statvfs.h>
+
+int
+statvfs (const char *path, struct statvfs *sb)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_location_info_t *fs_mount_root;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+ int result;
+
+ /*
+ * Get
+ * The root node of the mounted filesytem.
+ * The node for the directory that the fileystem is mounted on.
+ * The mount entry that is being refered to.
+ */
+
+ if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) )
+ return -1;
+
+ mt_entry = loc.mt_entry;
+ fs_mount_root = &mt_entry->mt_fs_root;
+
+ memset (sb, 0, sizeof (struct statvfs));
+
+ result = ( fs_mount_root->ops->statvfs_h )( fs_mount_root, sb );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/strlcat.c b/cpukit/libcsupport/src/strlcat.c
new file mode 100644
index 0000000000..b617cb93e8
--- /dev/null
+++ b/cpukit/libcsupport/src/strlcat.c
@@ -0,0 +1,41 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#ifndef HAVE_STRLCAT
+/*
+ * strlcat - like strcat/strncat, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcat(
+ char *dest,
+ const char *src,
+ size_t len )
+{
+ size_t dlen = strlen(dest);
+
+ return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
+}
+#endif
diff --git a/cpukit/libcsupport/src/strlcpy.c b/cpukit/libcsupport/src/strlcpy.c
new file mode 100644
index 0000000000..2773e877cb
--- /dev/null
+++ b/cpukit/libcsupport/src/strlcpy.c
@@ -0,0 +1,49 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#ifndef HAVE_STRLCPY
+/*
+ * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcpy(dest, src, len)
+ char *dest;
+ const char *src;
+ size_t len;
+{
+ size_t ret = strlen(src);
+
+ if (len != 0) {
+ if (ret < len)
+ strcpy(dest, src);
+ else {
+ strncpy(dest, src, len - 1);
+ dest[len-1] = 0;
+ }
+ }
+ return ret;
+}
+#endif
diff --git a/cpukit/libcsupport/src/sup_fs_get_start_loc.c b/cpukit/libcsupport/src/sup_fs_get_start_loc.c
new file mode 100644
index 0000000000..89f7efbb0d
--- /dev/null
+++ b/cpukit/libcsupport/src/sup_fs_get_start_loc.c
@@ -0,0 +1,48 @@
+ /**
+ * @file src/sup_fs_get_start_loc.c
+ */
+
+/*
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Function to determine if path is absolute or relative
+ *
+ * Parameters:
+ *
+ * path : IN - path to be checked
+ * index: OUT - 0, if relative, 1 if absolute
+ * loc : OUT - location info of root fs if absolute
+ * location info of current fs if relative
+ *
+ * Returns: void
+ */
+
+/* Includes */
+
+#include "rtems/libio_.h"
+
+void rtems_filesystem_get_start_loc(const char *path,
+ int *index,
+ rtems_filesystem_location_info_t *loc)
+{
+ if (rtems_filesystem_is_separator(path[0])) {
+ *loc = rtems_filesystem_root;
+ *index = 1;
+ }
+ else {
+ *loc = rtems_filesystem_current;
+ *index = 0;
+ }
+}
diff --git a/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c b/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c
new file mode 100644
index 0000000000..4bcc964a46
--- /dev/null
+++ b/cpukit/libcsupport/src/sup_fs_get_sym_start_loc.c
@@ -0,0 +1,47 @@
+ /**
+ * @file src/sup_fs_get_sym_start_loc.c
+ */
+
+/*
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+/*
+ * rtems_filesystem_get_sym_start_loc
+ *
+ * Function to determine if path is absolute or relative
+ *
+ * Parameters:
+ *
+ * path : IN - path to be checked
+ * index: OUT - 0, if relative, 1 if absolute
+ * loc : OUT - location info of root fs if absolute
+ * location info of current fs if relative
+ *
+ * Returns: void
+ */
+
+/* Includes */
+
+#include "rtems/libio_.h"
+
+void rtems_filesystem_get_sym_start_loc(const char *path,
+ int *index,
+ rtems_filesystem_location_info_t *loc)
+{
+ if (rtems_filesystem_is_separator(path[0])) {
+ *loc = rtems_filesystem_root;
+ *index = 1;
+ }
+ else {
+ *index = 0;
+ }
+}
diff --git a/cpukit/libcsupport/src/sup_fs_is_separator.c b/cpukit/libcsupport/src/sup_fs_is_separator.c
new file mode 100644
index 0000000000..affd606271
--- /dev/null
+++ b/cpukit/libcsupport/src/sup_fs_is_separator.c
@@ -0,0 +1,30 @@
+/**
+ * @file src/sup_fs_is_separator.c
+ */
+
+/*
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Function to determine if a character is a path name separator.
+ * This was originally a macro in libio_.h
+ *
+ * NOTE: This function handles MS-DOS and UNIX style names.
+ */
+
+int rtems_filesystem_is_separator(char ch)
+{
+ return ((ch == '/') || (ch == '\\') || (ch == '\0'));
+}
diff --git a/cpukit/libcsupport/src/symlink.c b/cpukit/libcsupport/src/symlink.c
new file mode 100644
index 0000000000..be29980911
--- /dev/null
+++ b/cpukit/libcsupport/src/symlink.c
@@ -0,0 +1,42 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.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_h)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ result = (*loc.ops->symlink_h)( &loc, actualpath, name_start);
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/sync.c b/cpukit/libcsupport/src/sync.c
new file mode 100644
index 0000000000..e1deefc293
--- /dev/null
+++ b/cpukit/libcsupport/src/sync.c
@@ -0,0 +1,101 @@
+/*
+ * sync() - XXX ??? where is this defined
+ *
+ * This function operates by as follows:
+ * for all threads
+ * for all FILE *
+ * fsync()
+ * fdatasync()
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+int fdatasync(int); /* still not always prototyped */
+
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <rtems.h>
+/*
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+*/
+
+/* XXX check standards -- Linux version appears to be void */
+void _fwalk(struct _reent *, void *);
+
+
+static void sync_wrapper(FILE *f)
+{
+ int fn = fileno(f);
+
+ /*
+ * We are explicitly NOT checking the return values as it does not
+ * matter if they succeed. We are just making a best faith attempt
+ * at both and trusting that we were passed a good FILE pointer.
+ */
+ fsync(fn);
+ fdatasync(fn);
+}
+
+/* iterate over all FILE *'s for this thread */
+static void sync_per_thread(Thread_Control *t)
+{
+ struct _reent *current_reent;
+ struct _reent *this_reent;
+
+ /*
+ * The sync_wrapper() function will operate on the current thread's
+ * reent structure so we will temporarily use that.
+ */
+ this_reent = t->libc_reent;
+ if ( this_reent ) {
+ current_reent = _Thread_Executing->libc_reent;
+ _Thread_Executing->libc_reent = this_reent;
+ _fwalk (t->libc_reent, sync_wrapper);
+ _Thread_Executing->libc_reent = current_reent;
+ }
+}
+
+/*
+ * _global_impure_ptr is not prototyped in any .h files.
+ * We have to extern it here.
+ */
+extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+
+void sync(void)
+{
+
+ /*
+ * Walk the one used initially by RTEMS.
+ */
+ _fwalk(_global_impure_ptr, sync_wrapper);
+
+ /*
+ * XXX Do we walk the one used globally by newlib?
+ * XXX Do we need the RTEMS global one?
+ */
+
+ /*
+ * Now walk all the per-thread reentrancy structures.
+ */
+ rtems_iterate_over_all_threads(sync_per_thread);
+}
diff --git a/cpukit/libcsupport/src/tcdrain.c b/cpukit/libcsupport/src/tcdrain.c
new file mode 100644
index 0000000000..c2e9d5e2ee
--- /dev/null
+++ b/cpukit/libcsupport/src/tcdrain.c
@@ -0,0 +1,36 @@
+/*
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/libio.h>
+
+int tcdrain(
+ int fd
+)
+{
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcflow.c b/cpukit/libcsupport/src/tcflow.c
new file mode 100644
index 0000000000..d4d3945f38
--- /dev/null
+++ b/cpukit/libcsupport/src/tcflow.c
@@ -0,0 +1,44 @@
+/*
+ * tcflow() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB)
+#include <termios.h>
+#include <unistd.h>
+#include <errno.h>
+#include <rtems/seterr.h>
+
+int tcflow (
+ int fd __attribute__((unused)),
+ int action
+)
+{
+ switch (action) {
+ case TCOOFF:
+ case TCOON:
+ case TCIOFF:
+ case TCION:
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* fd is not validated */
+
+ /* When this is supported, implement it here */
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcflush.c b/cpukit/libcsupport/src/tcflush.c
new file mode 100644
index 0000000000..6546966384
--- /dev/null
+++ b/cpukit/libcsupport/src/tcflush.c
@@ -0,0 +1,50 @@
+/*
+ * tcflush() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/seterr.h>
+#include <rtems/libio.h>
+
+int tcflush (
+ int fd __attribute__((unused)),
+ int queue
+)
+{
+ switch (queue) {
+ case TCIFLUSH:
+ case TCOFLUSH:
+ case TCIOFLUSH:
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* fd is not validated */
+
+ /* When this is supported, implement it here */
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcgetattr.c b/cpukit/libcsupport/src/tcgetattr.c
new file mode 100644
index 0000000000..8d4eb0618b
--- /dev/null
+++ b/cpukit/libcsupport/src/tcgetattr.c
@@ -0,0 +1,36 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/libio.h>
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/cpukit/libcsupport/src/tcgetpgrp.c b/cpukit/libcsupport/src/tcgetpgrp.c
new file mode 100644
index 0000000000..8894e46eef
--- /dev/null
+++ b/cpukit/libcsupport/src/tcgetpgrp.c
@@ -0,0 +1,28 @@
+/*
+ * tcgetprgrp() - POSIX 1003.1b 7.2.3 - Get Foreground Process Group ID
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(RTEMS_NEWLIB) && !defined(HAVE_TCGETPGRP)
+
+#include <sys/types.h>
+#include <unistd.h>
+
+pid_t tcgetpgrp(int fd __attribute__((unused)))
+{
+ return getpid();
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcsendbreak.c b/cpukit/libcsupport/src/tcsendbreak.c
new file mode 100644
index 0000000000..300e7a8f85
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsendbreak.c
@@ -0,0 +1,36 @@
+/*
+ * tcsendbreak() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/libio.h>
+
+int tcsendbreak (
+ int fd __attribute__((unused)),
+ int duration __attribute__((unused)) )
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcsetattr.c b/cpukit/libcsupport/src/tcsetattr.c
new file mode 100644
index 0000000000..187c1df584
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsetattr.c
@@ -0,0 +1,51 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ switch (opt) {
+ default:
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ case TCSADRAIN:
+ if (ioctl( fd, RTEMS_IO_TCDRAIN, NULL ) < 0)
+ return -1;
+ /*
+ * Fall through to....
+ */
+ case TCSANOW:
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+ }
+}
+#endif
diff --git a/cpukit/libcsupport/src/tcsetpgrp.c b/cpukit/libcsupport/src/tcsetpgrp.c
new file mode 100644
index 0000000000..f8e48025b6
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsetpgrp.c
@@ -0,0 +1,36 @@
+/*
+ * tcsetprgrp() - POSIX 1003.1b 7.2.4 - Set Foreground Process Group ID
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <rtems/libio.h>
+
+int tcsetpgrp(
+ int fd __attribute__((unused)),
+ pid_t pid __attribute__((unused)) )
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
new file mode 100644
index 0000000000..4085c5e4a2
--- /dev/null
+++ b/cpukit/libcsupport/src/termios.c
@@ -0,0 +1,1480 @@
+/*
+ * TERMIOS serial line support
+ *
+ * Author:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ttycom.h>
+
+#include <rtems/termiostypes.h>
+
+/*
+ * The size of the cooked buffer
+ */
+#define CBUFSIZE (rtems_termios_cbufsize)
+
+/*
+ * The sizes of the raw message buffers.
+ * On most architectures it is quite a bit more
+ * efficient if these are powers of two.
+ */
+#define RAW_INPUT_BUFFER_SIZE (rtems_termios_raw_input_size)
+#define RAW_OUTPUT_BUFFER_SIZE (rtems_termios_raw_output_size)
+
+/* fields for "flow_ctrl" status */
+#define FL_IREQXOF 1 /* input queue requests stop of incoming data */
+#define FL_ISNTXOF 2 /* XOFF has been sent to other side of line */
+#define FL_IRTSOFF 4 /* RTS has been turned off for other side.. */
+
+#define FL_ORCVXOF 0x10 /* XOFF has been received */
+#define FL_OSTOP 0x20 /* output has been stopped due to XOFF */
+
+#define FL_MDRTS 0x100 /* input controlled with RTS/CTS handshake */
+#define FL_MDXON 0x200 /* input controlled with XON/XOFF protocol */
+#define FL_MDXOF 0x400 /* output controlled with XON/XOFF protocol */
+
+#define NODISC(n) \
+ { NULL, NULL, NULL, NULL, \
+ NULL, NULL, NULL, NULL }
+/*
+ * FIXME: change rtems_termios_linesw entries consistent
+ * with rtems_termios_linesw entry usage...
+ */
+struct rtems_termios_linesw rtems_termios_linesw[MAXLDISC] =
+{
+ NODISC(0), /* 0- termios-built-in */
+ NODISC(1), /* 1- defunct */
+ NODISC(2), /* 2- NTTYDISC */
+ NODISC(3), /* TABLDISC */
+ NODISC(4), /* SLIPDISC */
+ NODISC(5), /* PPPDISC */
+ NODISC(6), /* loadable */
+ NODISC(7), /* loadable */
+};
+
+int rtems_termios_nlinesw =
+ sizeof (rtems_termios_linesw) / sizeof (rtems_termios_linesw[0]);
+
+extern struct rtems_termios_tty *rtems_termios_ttyHead;
+extern struct rtems_termios_tty *rtems_termios_ttyTail;
+extern rtems_id rtems_termios_ttyMutex;
+
+static int rtems_termios_cbufsize = 256;
+static int rtems_termios_raw_input_size = 128;
+static int rtems_termios_raw_output_size = 64;
+
+static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument);
+static rtems_task rtems_termios_txdaemon(rtems_task_argument argument);
+/*
+ * some constants for I/O daemon task creation
+ */
+#define TERMIOS_TXTASK_PRIO 10
+#define TERMIOS_RXTASK_PRIO 9
+#define TERMIOS_TXTASK_STACKSIZE 1024
+#define TERMIOS_RXTASK_STACKSIZE 1024
+/*
+ * some events to be sent to the I/O tasks
+ */
+#define TERMIOS_TX_START_EVENT RTEMS_EVENT_1
+#define TERMIOS_TX_TERMINATE_EVENT RTEMS_EVENT_0
+
+#define TERMIOS_RX_PROC_EVENT RTEMS_EVENT_1
+#define TERMIOS_RX_TERMINATE_EVENT RTEMS_EVENT_0
+
+/*
+ * Open a termios device
+ */
+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 sc;
+ rtems_libio_open_close_args_t *args = arg;
+ struct rtems_termios_tty *tty;
+
+ /*
+ * See if the device has already been opened
+ */
+ sc = rtems_semaphore_obtain(
+ rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ for (tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw) {
+ if ((tty->major == major) && (tty->minor == minor))
+ break;
+ }
+
+ if (tty == NULL) {
+ static char c = 'a';
+
+ /*
+ * Create a new device
+ */
+ tty = calloc (1, sizeof (struct rtems_termios_tty));
+ if (tty == NULL) {
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate raw input buffer
+ */
+ tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE;
+ tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size);
+ if (tty->rawInBuf.theBuf == NULL) {
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate raw output buffer
+ */
+ tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE;
+ tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size);
+ if (tty->rawOutBuf.theBuf == NULL) {
+ free((void *)(tty->rawInBuf.theBuf));
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate cooked buffer
+ */
+ tty->cbuf = malloc (CBUFSIZE);
+ if (tty->cbuf == NULL) {
+ free((void *)(tty->rawOutBuf.theBuf));
+ free((void *)(tty->rawInBuf.theBuf));
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * Initialize wakeup callbacks
+ */
+ tty->tty_snd.sw_pfn = NULL;
+ tty->tty_snd.sw_arg = NULL;
+ tty->tty_rcv.sw_pfn = NULL;
+ tty->tty_rcv.sw_arg = NULL;
+ tty->tty_rcvwakeup = 0;
+
+ /*
+ * link tty
+ */
+ tty->forw = rtems_termios_ttyHead;
+ tty->back = NULL;
+ if (rtems_termios_ttyHead != NULL)
+ rtems_termios_ttyHead->back = tty;
+ rtems_termios_ttyHead = tty;
+ if (rtems_termios_ttyTail == NULL)
+ rtems_termios_ttyTail = tty;
+
+ tty->minor = minor;
+ tty->major = major;
+
+ /*
+ * Set up mutex semaphores
+ */
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'i', c),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->isem);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'o', c),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->osem);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'x', c),
+ 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO,
+ RTEMS_NO_PRIORITY,
+ &tty->rawOutBuf.Semaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ tty->rawOutBufState = rob_idle;
+
+ /*
+ * Set callbacks
+ */
+ tty->device = *callbacks;
+
+ /*
+ * Create I/O tasks
+ */
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ sc = rtems_task_create (
+ rtems_build_name ('T', 'x', 'T', c),
+ TERMIOS_TXTASK_PRIO,
+ TERMIOS_TXTASK_STACKSIZE,
+ RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
+ RTEMS_NO_ASR,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tty->txTaskId);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_task_create (
+ rtems_build_name ('R', 'x', 'T', c),
+ TERMIOS_RXTASK_PRIO,
+ TERMIOS_RXTASK_STACKSIZE,
+ RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
+ RTEMS_NO_ASR,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tty->rxTaskId);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ }
+ if ((tty->device.pollRead == NULL) ||
+ (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)){
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'r', c),
+ 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->rawInBuf.Semaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+
+ /*
+ * Set default parameters
+ */
+ tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
+ tty->termios.c_oflag = OPOST | ONLCR | XTABS;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
+ tty->termios.c_lflag =
+ ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
+
+ tty->termios.c_cc[VINTR] = '\003';
+ tty->termios.c_cc[VQUIT] = '\034';
+ tty->termios.c_cc[VERASE] = '\177';
+ tty->termios.c_cc[VKILL] = '\025';
+ tty->termios.c_cc[VEOF] = '\004';
+ tty->termios.c_cc[VEOL] = '\000';
+ tty->termios.c_cc[VEOL2] = '\000';
+ tty->termios.c_cc[VSTART] = '\021';
+ tty->termios.c_cc[VSTOP] = '\023';
+ tty->termios.c_cc[VSUSP] = '\032';
+ tty->termios.c_cc[VREPRINT] = '\022';
+ tty->termios.c_cc[VDISCARD] = '\017';
+ tty->termios.c_cc[VWERASE] = '\027';
+ tty->termios.c_cc[VLNEXT] = '\026';
+
+ /* start with no flow control, clear flow control flags */
+ tty->flow_ctrl = 0;
+ /*
+ * set low/highwater mark for XON/XOFF support
+ */
+ tty->lowwater = tty->rawInBuf.Size * 1/2;
+ tty->highwater = tty->rawInBuf.Size * 3/4;
+ /*
+ * Bump name characer
+ */
+ if (c++ == 'z')
+ c = 'a';
+
+ }
+ args->iop->data1 = tty;
+ if (!tty->refcount++) {
+ if (tty->device.firstOpen)
+ (*tty->device.firstOpen)(major, minor, arg);
+
+ /*
+ * start I/O tasks, if needed
+ */
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ sc = rtems_task_start(
+ tty->rxTaskId, rtems_termios_rxdaemon, (rtems_task_argument)tty);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ sc = rtems_task_start(
+ tty->txTaskId, rtems_termios_txdaemon, (rtems_task_argument)tty);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+ }
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Drain output queue
+ */
+static void
+drainOutput (struct rtems_termios_tty *tty)
+{
+ rtems_interrupt_level level;
+ rtems_status_code sc;
+
+ if (tty->device.outputUsesInterrupts != TERMIOS_POLLED) {
+ rtems_interrupt_disable (level);
+ while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
+ tty->rawOutBufState = rob_wait;
+ rtems_interrupt_enable (level);
+ sc = rtems_semaphore_obtain(
+ tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ rtems_interrupt_disable (level);
+ }
+ rtems_interrupt_enable (level);
+ }
+}
+
+rtems_status_code
+rtems_termios_close (void *arg)
+{
+ rtems_libio_open_close_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain(
+ rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ if (--tty->refcount == 0) {
+ if (rtems_termios_linesw[tty->t_line].l_close != NULL) {
+ /*
+ * call discipline-specific close
+ */
+ sc = rtems_termios_linesw[tty->t_line].l_close(tty);
+ } else {
+ /*
+ * default: just flush output buffer
+ */
+ sc = rtems_semaphore_obtain(tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred (sc);
+ }
+ drainOutput (tty);
+ rtems_semaphore_release (tty->osem);
+ }
+
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ /*
+ * send "terminate" to I/O tasks
+ */
+ sc = rtems_event_send( tty->rxTaskId, TERMIOS_RX_TERMINATE_EVENT );
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_event_send( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT );
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+ if (tty->device.lastClose)
+ (*tty->device.lastClose)(tty->major, tty->minor, arg);
+ if (tty->forw == NULL) {
+ rtems_termios_ttyTail = tty->back;
+ if ( rtems_termios_ttyTail != NULL ) {
+ rtems_termios_ttyTail->forw = NULL;
+ }
+ } else {
+ tty->forw->back = tty->back;
+ }
+
+ if (tty->back == NULL) {
+ rtems_termios_ttyHead = tty->forw;
+ if ( rtems_termios_ttyHead != NULL ) {
+ rtems_termios_ttyHead->back = NULL;
+ }
+ } else {
+ tty->back->forw = tty->forw;
+ }
+
+ rtems_semaphore_delete (tty->isem);
+ rtems_semaphore_delete (tty->osem);
+ rtems_semaphore_delete (tty->rawOutBuf.Semaphore);
+ if ((tty->device.pollRead == NULL) ||
+ (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN))
+ rtems_semaphore_delete (tty->rawInBuf.Semaphore);
+ free (tty->rawInBuf.theBuf);
+ free (tty->rawOutBuf.theBuf);
+ free (tty->cbuf);
+ free (tty);
+ }
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_termios_bufsize (
+ int cbufsize,
+ int raw_input,
+ int raw_output
+)
+{
+ rtems_termios_cbufsize = cbufsize;
+ rtems_termios_raw_input_size = raw_input;
+ rtems_termios_raw_output_size = raw_output;
+ return RTEMS_SUCCESSFUL;
+}
+
+static void
+termios_set_flowctrl(struct rtems_termios_tty *tty)
+{
+ rtems_interrupt_level level;
+ /*
+ * check for flow control options to be switched off
+ */
+
+ /* check for outgoing XON/XOFF flow control switched off */
+ if (( tty->flow_ctrl & FL_MDXON) &&
+ !(tty->termios.c_iflag & IXON)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDXON | FL_ORCVXOF);
+
+ /* has output been stopped due to received XOFF? */
+ if (tty->flow_ctrl & FL_OSTOP) {
+ /* disable interrupts */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl &= ~FL_OSTOP;
+ /* check for chars in output buffer (or rob_state?) */
+ if (tty->rawOutBufState != rob_idle) {
+ /* if chars available, call write function... */
+ (*tty->device.write)(
+ tty->minor, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+ }
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+ }
+ }
+ /* check for incoming XON/XOFF flow control switched off */
+ if (( tty->flow_ctrl & FL_MDXOF) && !(tty->termios.c_iflag & IXOFF)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDXOF);
+ /* FIXME: what happens, if we had sent XOFF but not yet XON? */
+ tty->flow_ctrl &= ~(FL_ISNTXOF);
+ }
+
+ /* check for incoming RTS/CTS flow control switched off */
+ if (( tty->flow_ctrl & FL_MDRTS) && !(tty->termios.c_cflag & CRTSCTS)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDRTS);
+
+ /* restart remote Tx, if it was stopped */
+ if ((tty->flow_ctrl & FL_IRTSOFF) && (tty->device.startRemoteTx != NULL)) {
+ tty->device.startRemoteTx(tty->minor);
+ }
+ tty->flow_ctrl &= ~(FL_IRTSOFF);
+ }
+
+ /*
+ * check for flow control options to be switched on
+ */
+ /* check for incoming RTS/CTS flow control switched on */
+ if (tty->termios.c_cflag & CRTSCTS) {
+ tty->flow_ctrl |= FL_MDRTS;
+ }
+ /* check for incoming XON/XOF flow control switched on */
+ if (tty->termios.c_iflag & IXOFF) {
+ tty->flow_ctrl |= FL_MDXOF;
+ }
+ /* check for outgoing XON/XOF flow control switched on */
+ if (tty->termios.c_iflag & IXON) {
+ tty->flow_ctrl |= FL_MDXON;
+ }
+}
+
+rtems_status_code
+rtems_termios_ioctl (void *arg)
+{
+ rtems_libio_ioctl_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ struct ttywakeup *wakeup = (struct ttywakeup *)args->buffer;
+ rtems_status_code sc;
+
+ args->ioctl_return = 0;
+ sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL) {
+ args->ioctl_return = sc;
+ return sc;
+ }
+ switch (args->command) {
+ default:
+ if (rtems_termios_linesw[tty->t_line].l_ioctl != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_ioctl(tty,args);
+ }
+ else {
+ sc = RTEMS_INVALID_NUMBER;
+ }
+ break;
+
+ case RTEMS_IO_GET_ATTRIBUTES:
+ *(struct termios *)args->buffer = tty->termios;
+ break;
+
+ case RTEMS_IO_SET_ATTRIBUTES:
+ tty->termios = *(struct termios *)args->buffer;
+
+ /* check for and process change in flow control options */
+ termios_set_flowctrl(tty);
+
+ if (tty->termios.c_lflag & ICANON) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ } else {
+ tty->vtimeTicks = tty->termios.c_cc[VTIME] *
+ rtems_clock_get_ticks_per_second() / 10;
+ if (tty->termios.c_cc[VTIME]) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
+ if (tty->termios.c_cc[VMIN])
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ else
+ tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
+ } else {
+ if (tty->termios.c_cc[VMIN]) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ } else {
+ tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
+ }
+ }
+ }
+ if (tty->device.setAttributes)
+ (*tty->device.setAttributes)(tty->minor, &tty->termios);
+ break;
+
+ case RTEMS_IO_TCDRAIN:
+ drainOutput (tty);
+ break;
+
+ case RTEMS_IO_SNDWAKEUP:
+ tty->tty_snd = *wakeup;
+ break;
+
+ case RTEMS_IO_RCVWAKEUP:
+ tty->tty_rcv = *wakeup;
+ break;
+
+ /*
+ * FIXME: add various ioctl code handlers
+ */
+
+#if 1 /* FIXME */
+ case TIOCSETD:
+ /*
+ * close old line discipline
+ */
+ if (rtems_termios_linesw[tty->t_line].l_close != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_close(tty);
+ }
+ tty->t_line=*(int*)(args->buffer);
+ tty->t_sc = NULL; /* ensure that no more valid data */
+ /*
+ * open new line discipline
+ */
+ if (rtems_termios_linesw[tty->t_line].l_open != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_open(tty);
+ }
+ break;
+ case TIOCGETD:
+ *(int*)(args->buffer)=tty->t_line;
+ break;
+#endif
+ case FIONREAD: {
+ int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head;
+ if ( rawnc < 0 )
+ rawnc += tty->rawInBuf.Size;
+ /* Half guess that this is the right operation */
+ *(int *)args->buffer = tty->ccount - tty->cindex + rawnc;
+ }
+ break;
+ }
+
+ rtems_semaphore_release (tty->osem);
+ args->ioctl_return = sc;
+ return sc;
+}
+
+/*
+ * Send characters to device-specific code
+ */
+void
+rtems_termios_puts (
+ const void *_buf, int len, struct rtems_termios_tty *tty)
+{
+ const unsigned char *buf = _buf;
+ unsigned int newHead;
+ rtems_interrupt_level level;
+ rtems_status_code sc;
+
+ if (tty->device.outputUsesInterrupts == TERMIOS_POLLED) {
+ (*tty->device.write)(tty->minor, (void *)buf, len);
+ return;
+ }
+ newHead = tty->rawOutBuf.Head;
+ while (len) {
+ /*
+ * Performance improvement could be made here.
+ * Copy multiple bytes to raw buffer:
+ * if (len > 1) && (space to buffer end, or tail > 1)
+ * ncopy = MIN (len, space to buffer end or tail)
+ * memcpy (raw buffer, buf, ncopy)
+ * buf += ncopy
+ * len -= ncopy
+ *
+ * To minimize latency, the memcpy should be done
+ * with interrupts enabled.
+ */
+ newHead = (newHead + 1) % tty->rawOutBuf.Size;
+ rtems_interrupt_disable (level);
+ while (newHead == tty->rawOutBuf.Tail) {
+ tty->rawOutBufState = rob_wait;
+ rtems_interrupt_enable (level);
+ sc = rtems_semaphore_obtain(
+ tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ rtems_interrupt_disable (level);
+ }
+ tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++;
+ tty->rawOutBuf.Head = newHead;
+ if (tty->rawOutBufState == rob_idle) {
+ /* check, whether XOFF has been received */
+ if (!(tty->flow_ctrl & FL_ORCVXOF)) {
+ (*tty->device.write)(tty->minor,
+ (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+ } else {
+ /* remember that output has been stopped due to flow ctrl*/
+ tty->flow_ctrl |= FL_OSTOP;
+ }
+ tty->rawOutBufState = rob_busy;
+ }
+ rtems_interrupt_enable (level);
+ len--;
+ }
+}
+
+/*
+ * Handle output processing
+ */
+static void
+oproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ int i;
+
+ if (tty->termios.c_oflag & OPOST) {
+ switch (c) {
+ case '\n':
+ if (tty->termios.c_oflag & ONLRET)
+ tty->column = 0;
+ if (tty->termios.c_oflag & ONLCR) {
+ rtems_termios_puts ("\r", 1, tty);
+ tty->column = 0;
+ }
+ break;
+
+ case '\r':
+ if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
+ return;
+ if (tty->termios.c_oflag & OCRNL) {
+ c = '\n';
+ if (tty->termios.c_oflag & ONLRET)
+ tty->column = 0;
+ break;
+ }
+ tty->column = 0;
+ break;
+
+ case '\t':
+ i = 8 - (tty->column & 7);
+ if ((tty->termios.c_oflag & TABDLY) == XTABS) {
+ tty->column += i;
+ rtems_termios_puts ( " ", i, tty);
+ return;
+ }
+ tty->column += i;
+ break;
+
+ case '\b':
+ if (tty->column > 0)
+ tty->column--;
+ break;
+
+ default:
+ if (tty->termios.c_oflag & OLCUC)
+ c = toupper(c);
+ if (!iscntrl(c))
+ tty->column++;
+ break;
+ }
+ }
+ rtems_termios_puts (&c, 1, tty);
+}
+
+rtems_status_code
+rtems_termios_write (void *arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+ if (rtems_termios_linesw[tty->t_line].l_write != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_write(tty,args);
+ rtems_semaphore_release (tty->osem);
+ return sc;
+ }
+ if (tty->termios.c_oflag & OPOST) {
+ uint32_t count = args->count;
+ char *buffer = args->buffer;
+ while (count--)
+ oproc (*buffer++, tty);
+ args->bytes_moved = args->count;
+ } else {
+ rtems_termios_puts (args->buffer, args->count, tty);
+ args->bytes_moved = args->count;
+ }
+ rtems_semaphore_release (tty->osem);
+ return sc;
+}
+
+/*
+ * Echo a typed character
+ */
+static void
+echo (unsigned char c, struct rtems_termios_tty *tty)
+{
+ if ((tty->termios.c_lflag & ECHOCTL) &&
+ iscntrl(c) && (c != '\t') && (c != '\n')) {
+ char echobuf[2];
+
+ echobuf[0] = '^';
+ echobuf[1] = c ^ 0x40;
+ rtems_termios_puts (echobuf, 2, tty);
+ tty->column += 2;
+ } else {
+ oproc (c, tty);
+ }
+}
+
+/*
+ * Erase a character or line
+ * FIXME: Needs support for WERASE and ECHOPRT.
+ * FIXME: Some of the tests should check for IEXTEN, too.
+ */
+static void
+erase (struct rtems_termios_tty *tty, int lineFlag)
+{
+ if (tty->ccount == 0)
+ return;
+ if (lineFlag) {
+ if (!(tty->termios.c_lflag & ECHO)) {
+ tty->ccount = 0;
+ return;
+ }
+ if (!(tty->termios.c_lflag & ECHOE)) {
+ tty->ccount = 0;
+ echo (tty->termios.c_cc[VKILL], tty);
+ if (tty->termios.c_lflag & ECHOK)
+ echo ('\n', tty);
+ return;
+ }
+ }
+
+ while (tty->ccount) {
+ unsigned char c = tty->cbuf[--tty->ccount];
+
+ if (tty->termios.c_lflag & ECHO) {
+ if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
+ echo (tty->termios.c_cc[VERASE], tty);
+ } else if (c == '\t') {
+ int col = tty->read_start_column;
+ int i = 0;
+
+ /*
+ * Find the character before the tab
+ */
+ while (i != tty->ccount) {
+ c = tty->cbuf[i++];
+ if (c == '\t') {
+ col = (col | 7) + 1;
+ } else if (iscntrl (c)) {
+ if (tty->termios.c_lflag & ECHOCTL)
+ col += 2;
+ } else {
+ col++;
+ }
+ }
+
+ /*
+ * Back up over the tab
+ */
+ while (tty->column > col) {
+ rtems_termios_puts ("\b", 1, tty);
+ tty->column--;
+ }
+ }
+ else {
+ if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
+ rtems_termios_puts ("\b \b", 3, tty);
+ if (tty->column)
+ tty->column--;
+ }
+ if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
+ rtems_termios_puts ("\b \b", 3, tty);
+ if (tty->column)
+ tty->column--;
+ }
+ }
+ }
+ if (!lineFlag)
+ break;
+ }
+}
+
+/*
+ * Process a single input character
+ */
+static int
+iproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ if (tty->termios.c_iflag & ISTRIP)
+ c &= 0x7f;
+
+ if (tty->termios.c_iflag & IUCLC)
+ c = tolower (c);
+
+ if (c == '\r') {
+ if (tty->termios.c_iflag & IGNCR)
+ return 0;
+ if (tty->termios.c_iflag & ICRNL)
+ c = '\n';
+ } else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
+ c = '\r';
+ }
+
+ if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
+ if (c == tty->termios.c_cc[VERASE]) {
+ erase (tty, 0);
+ return 0;
+ }
+ else if (c == tty->termios.c_cc[VKILL]) {
+ erase (tty, 1);
+ return 0;
+ }
+ else if (c == tty->termios.c_cc[VEOF]) {
+ return 1;
+ } else if (c == '\n') {
+ if (tty->termios.c_lflag & (ECHO | ECHONL))
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ return 1;
+ } else if ((c == tty->termios.c_cc[VEOL]) ||
+ (c == tty->termios.c_cc[VEOL2])) {
+ if (tty->termios.c_lflag & ECHO)
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ return 1;
+ }
+ }
+
+ /*
+ * FIXME: Should do IMAXBEL handling somehow
+ */
+ if (tty->ccount < (CBUFSIZE-1)) {
+ if (tty->termios.c_lflag & ECHO)
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ }
+ return 0;
+}
+
+/*
+ * Process input character, with semaphore.
+ */
+static int
+siproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ int i;
+
+ /*
+ * Obtain output semaphore if character will be echoed
+ */
+ if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
+ rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ i = iproc (c, tty);
+ rtems_semaphore_release (tty->osem);
+ }
+ else {
+ i = iproc (c, tty);
+ }
+ return i;
+}
+
+/*
+ * Fill the input buffer by polling the device
+ */
+static rtems_status_code
+fillBufferPoll (struct rtems_termios_tty *tty)
+{
+ int n;
+
+ if (tty->termios.c_lflag & ICANON) {
+ for (;;) {
+ n = (*tty->device.pollRead)(tty->minor);
+ if (n < 0) {
+ rtems_task_wake_after (1);
+ } else {
+ if (siproc (n, tty))
+ break;
+ }
+ }
+ } else {
+ rtems_interval then, now;
+
+ then = rtems_clock_get_ticks_since_boot();
+ for (;;) {
+ n = (*tty->device.pollRead)(tty->minor);
+ if (n < 0) {
+ if (tty->termios.c_cc[VMIN]) {
+ if (tty->termios.c_cc[VTIME] && tty->ccount) {
+ now = rtems_clock_get_ticks_since_boot();
+ if ((now - then) > tty->vtimeTicks) {
+ break;
+ }
+ }
+ } else {
+ if (!tty->termios.c_cc[VTIME])
+ break;
+ now = rtems_clock_get_ticks_since_boot();
+ if ((now - then) > tty->vtimeTicks) {
+ break;
+ }
+ }
+ rtems_task_wake_after (1);
+ } else {
+ siproc (n, tty);
+ if (tty->ccount >= tty->termios.c_cc[VMIN])
+ break;
+ if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
+ then = rtems_clock_get_ticks_since_boot();
+ }
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Fill the input buffer from the raw input queue
+ */
+static rtems_status_code
+fillBufferQueue (struct rtems_termios_tty *tty)
+{
+ rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
+ rtems_status_code sc;
+ int wait = (int)1;
+
+ while ( wait ) {
+ /*
+ * Process characters read from raw queue
+ */
+ while ((tty->rawInBuf.Head != tty->rawInBuf.Tail) &&
+ (tty->ccount < (CBUFSIZE-1))) {
+ unsigned char c;
+ unsigned int newHead;
+
+ newHead = (tty->rawInBuf.Head + 1) % tty->rawInBuf.Size;
+ c = tty->rawInBuf.theBuf[newHead];
+ tty->rawInBuf.Head = newHead;
+ if(((tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size)
+ % tty->rawInBuf.Size)
+ < tty->lowwater) {
+ tty->flow_ctrl &= ~FL_IREQXOF;
+ /* if tx stopped and XON should be sent... */
+ if (((tty->flow_ctrl & (FL_MDXON | FL_ISNTXOF))
+ == (FL_MDXON | FL_ISNTXOF))
+ && ((tty->rawOutBufState == rob_idle)
+ || (tty->flow_ctrl & FL_OSTOP))) {
+ /* XON should be sent now... */
+ (*tty->device.write)(
+ tty->minor, (void *)&(tty->termios.c_cc[VSTART]), 1);
+ } else if (tty->flow_ctrl & FL_MDRTS) {
+ tty->flow_ctrl &= ~FL_IRTSOFF;
+ /* activate RTS line */
+ if (tty->device.startRemoteTx != NULL) {
+ tty->device.startRemoteTx(tty->minor);
+ }
+ }
+ }
+
+ /* continue processing new character */
+ if (tty->termios.c_lflag & ICANON) {
+ if (siproc (c, tty))
+ wait = 0;
+ } else {
+ siproc (c, tty);
+ if (tty->ccount >= tty->termios.c_cc[VMIN])
+ wait = 0;
+ }
+ timeout = tty->rawInBufSemaphoreTimeout;
+ }
+
+ /*
+ * Wait for characters
+ */
+ if ( wait ) {
+ sc = rtems_semaphore_obtain(
+ tty->rawInBuf.Semaphore, tty->rawInBufSemaphoreOptions, timeout);
+ if (sc != RTEMS_SUCCESSFUL)
+ break;
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code
+rtems_termios_read (void *arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ uint32_t count = args->count;
+ char *buffer = args->buffer;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ if (rtems_termios_linesw[tty->t_line].l_read != NULL) {
+ sc = rtems_termios_linesw[tty->t_line].l_read(tty,args);
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+ return sc;
+ }
+
+ if (tty->cindex == tty->ccount) {
+ tty->cindex = tty->ccount = 0;
+ tty->read_start_column = tty->column;
+ if (tty->device.pollRead != NULL &&
+ tty->device.outputUsesInterrupts == TERMIOS_POLLED)
+ sc = fillBufferPoll (tty);
+ else
+ sc = fillBufferQueue (tty);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ tty->cindex = tty->ccount = 0;
+ }
+ while (count && (tty->cindex < tty->ccount)) {
+ *buffer++ = tty->cbuf[tty->cindex++];
+ count--;
+ }
+ args->bytes_moved = args->count - count;
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+ return sc;
+}
+
+/*
+ * signal receive interrupt to rx daemon
+ * NOTE: This routine runs in the context of the
+ * device receive interrupt handler.
+ */
+void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty)
+{
+ /*
+ * send event to rx daemon task
+ */
+ rtems_event_send(tty->rxTaskId,TERMIOS_RX_PROC_EVENT);
+}
+
+/*
+ * Place characters on raw queue.
+ * NOTE: This routine runs in the context of the
+ * device receive interrupt handler.
+ * Returns the number of characters dropped because of overflow.
+ */
+int
+rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
+{
+ struct rtems_termios_tty *tty = ttyp;
+ unsigned int newTail;
+ char c;
+ int dropped = 0;
+ bool flow_rcv = false; /* true, if flow control char received */
+ rtems_interrupt_level level;
+
+ if (rtems_termios_linesw[tty->t_line].l_rint != NULL) {
+ while (len--) {
+ c = *buf++;
+ rtems_termios_linesw[tty->t_line].l_rint(c,tty);
+ }
+
+ /*
+ * check to see if rcv wakeup callback was set
+ */
+ if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) {
+ (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
+ tty->tty_rcvwakeup = 1;
+ }
+ return 0;
+ }
+
+ while (len--) {
+ c = *buf++;
+ /* FIXME: implement IXANY: any character restarts output */
+ /* if incoming XON/XOFF controls outgoing stream: */
+ if (tty->flow_ctrl & FL_MDXON) {
+ /* if received char is V_STOP and V_START (both are equal value) */
+ if (c == tty->termios.c_cc[VSTOP]) {
+ if (c == tty->termios.c_cc[VSTART]) {
+ /* received VSTOP and VSTART==VSTOP? */
+ /* then toggle "stop output" status */
+ tty->flow_ctrl = tty->flow_ctrl ^ FL_ORCVXOF;
+ }
+ else {
+ /* VSTOP received (other code than VSTART) */
+ /* stop output */
+ tty->flow_ctrl |= FL_ORCVXOF;
+ }
+ flow_rcv = true;
+ }
+ else if (c == tty->termios.c_cc[VSTART]) {
+ /* VSTART received */
+ /* restart output */
+ tty->flow_ctrl &= ~FL_ORCVXOF;
+ flow_rcv = true;
+ }
+ }
+ if (flow_rcv) {
+ /* restart output according to FL_ORCVXOF flag */
+ if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) {
+ /* disable interrupts */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl &= ~FL_OSTOP;
+ /* check for chars in output buffer (or rob_state?) */
+ if (tty->rawOutBufState != rob_idle) {
+ /* if chars available, call write function... */
+ (*tty->device.write)(
+ tty->minor, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
+ }
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+ }
+ } else {
+ newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size;
+ /* if chars_in_buffer > highwater */
+ rtems_interrupt_disable(level);
+ if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size)
+ % tty->rawInBuf.Size) > tty->highwater) &&
+ !(tty->flow_ctrl & FL_IREQXOF)) {
+ /* incoming data stream should be stopped */
+ tty->flow_ctrl |= FL_IREQXOF;
+ if ((tty->flow_ctrl & (FL_MDXOF | FL_ISNTXOF))
+ == (FL_MDXOF ) ) {
+ if ((tty->flow_ctrl & FL_OSTOP) ||
+ (tty->rawOutBufState == rob_idle)) {
+ /* if tx is stopped due to XOFF or out of data */
+ /* call write function here */
+ tty->flow_ctrl |= FL_ISNTXOF;
+ (*tty->device.write)(tty->minor,
+ (void *)&(tty->termios.c_cc[VSTOP]), 1);
+ }
+ } else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) == (FL_MDRTS) ) {
+ tty->flow_ctrl |= FL_IRTSOFF;
+ /* deactivate RTS line */
+ if (tty->device.stopRemoteTx != NULL) {
+ tty->device.stopRemoteTx(tty->minor);
+ }
+ }
+ }
+
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+
+ if (newTail == tty->rawInBuf.Head) {
+ dropped++;
+ } else {
+ tty->rawInBuf.theBuf[newTail] = c;
+ tty->rawInBuf.Tail = newTail;
+
+ /*
+ * check to see if rcv wakeup callback was set
+ */
+ if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) {
+ (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
+ tty->tty_rcvwakeup = 1;
+ }
+ }
+ }
+ }
+
+ tty->rawInBufDropped += dropped;
+ rtems_semaphore_release (tty->rawInBuf.Semaphore);
+ return dropped;
+}
+
+/*
+ * in task-driven mode, this function is called in Tx task context
+ * in interrupt-driven mode, this function is called in TxIRQ context
+ */
+int
+rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
+{
+ unsigned int newTail;
+ int nToSend;
+ rtems_interrupt_level level;
+ int len;
+
+ /* check for XOF/XON to send */
+ if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF))
+ == (FL_MDXOF | FL_IREQXOF)) {
+ /* XOFF should be sent now... */
+ (*tty->device.write)(tty->minor, (void *)&(tty->termios.c_cc[VSTOP]), 1);
+
+ rtems_interrupt_disable(level);
+ tty->t_dqlen--;
+ tty->flow_ctrl |= FL_ISNTXOF;
+ rtems_interrupt_enable(level);
+
+ nToSend = 1;
+
+ } else if ((tty->flow_ctrl & (FL_IREQXOF | FL_ISNTXOF)) == FL_ISNTXOF) {
+ /* NOTE: send XON even, if no longer in XON/XOFF mode... */
+ /* XON should be sent now... */
+ /*
+ * FIXME: this .write call will generate another
+ * dequeue callback. This will advance the "Tail" in the data
+ * buffer, although the corresponding data is not yet out!
+ * Therefore the dequeue "length" should be reduced by 1
+ */
+ (*tty->device.write)(tty->minor, (void *)&(tty->termios.c_cc[VSTART]), 1);
+
+ rtems_interrupt_disable(level);
+ tty->t_dqlen--;
+ tty->flow_ctrl &= ~FL_ISNTXOF;
+ rtems_interrupt_enable(level);
+
+ nToSend = 1;
+ } else {
+ if ( tty->rawOutBuf.Head == tty->rawOutBuf.Tail ) {
+ /*
+ * buffer was empty
+ */
+ if (tty->rawOutBufState == rob_wait) {
+ /*
+ * this should never happen...
+ */
+ rtems_semaphore_release (tty->rawOutBuf.Semaphore);
+ }
+ return 0;
+ }
+
+ rtems_interrupt_disable(level);
+ len = tty->t_dqlen;
+ tty->t_dqlen = 0;
+ rtems_interrupt_enable(level);
+
+ newTail = (tty->rawOutBuf.Tail + len) % tty->rawOutBuf.Size;
+ tty->rawOutBuf.Tail = newTail;
+ if (tty->rawOutBufState == rob_wait) {
+ /*
+ * wake up any pending writer task
+ */
+ rtems_semaphore_release (tty->rawOutBuf.Semaphore);
+ }
+
+ if (newTail == tty->rawOutBuf.Head) {
+ /*
+ * Buffer has become empty
+ */
+ tty->rawOutBufState = rob_idle;
+ nToSend = 0;
+
+ /*
+ * check to see if snd wakeup callback was set
+ */
+ if ( tty->tty_snd.sw_pfn != NULL) {
+ (*tty->tty_snd.sw_pfn)(&tty->termios, tty->tty_snd.sw_arg);
+ }
+ }
+ /* check, whether output should stop due to received XOFF */
+ else if ((tty->flow_ctrl & (FL_MDXON | FL_ORCVXOF))
+ == (FL_MDXON | FL_ORCVXOF)) {
+ /* Buffer not empty, but output stops due to XOFF */
+ /* set flag, that output has been stopped */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl |= FL_OSTOP;
+ tty->rawOutBufState = rob_busy; /*apm*/
+ rtems_interrupt_enable(level);
+ nToSend = 0;
+ } else {
+ /*
+ * Buffer not empty, start tranmitter
+ */
+ if (newTail > tty->rawOutBuf.Head)
+ nToSend = tty->rawOutBuf.Size - newTail;
+ else
+ nToSend = tty->rawOutBuf.Head - newTail;
+ /* when flow control XON or XOF, don't send blocks of data */
+ /* to allow fast reaction on incoming flow ctrl and low latency*/
+ /* for outgoing flow control */
+ if (tty->flow_ctrl & (FL_MDXON | FL_MDXOF)) {
+ nToSend = 1;
+ }
+ tty->rawOutBufState = rob_busy; /*apm*/
+ (*tty->device.write)(
+ tty->minor, &tty->rawOutBuf.theBuf[newTail], nToSend);
+ }
+ tty->rawOutBuf.Tail = newTail; /*apm*/
+ }
+ return nToSend;
+}
+
+/*
+ * Characters have been transmitted
+ * NOTE: This routine runs in the context of the
+ * device transmit interrupt handler.
+ * The second argument is the number of characters transmitted so far.
+ * This value will always be 1 for devices which generate an interrupt
+ * for each transmitted character.
+ * It returns number of characters left to transmit
+ */
+int
+rtems_termios_dequeue_characters (void *ttyp, int len)
+{
+ struct rtems_termios_tty *tty = ttyp;
+ rtems_status_code sc;
+
+ /*
+ * sum up character count already sent
+ */
+ tty->t_dqlen += len;
+
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ /*
+ * send wake up to transmitter task
+ */
+ sc = rtems_event_send(tty->txTaskId, TERMIOS_TX_START_EVENT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ return 0; /* nothing to output in IRQ... */
+ }
+
+ if (tty->t_line == PPPDISC ) {
+ /*
+ * call any line discipline start function
+ */
+ if (rtems_termios_linesw[tty->t_line].l_start != NULL) {
+ rtems_termios_linesw[tty->t_line].l_start(tty);
+ }
+ return 0; /* nothing to output in IRQ... */
+ }
+
+ return rtems_termios_refill_transmitter(tty);
+}
+
+/*
+ * this task actually processes any transmit events
+ */
+static rtems_task rtems_termios_txdaemon(rtems_task_argument argument)
+{
+ struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+ rtems_event_set the_event;
+
+ while (1) {
+ /*
+ * wait for rtems event
+ */
+ rtems_event_receive(
+ (TERMIOS_TX_START_EVENT | TERMIOS_TX_TERMINATE_EVENT),
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &the_event
+ );
+ if ((the_event & TERMIOS_TX_TERMINATE_EVENT) != 0) {
+ tty->txTaskId = 0;
+ rtems_task_delete(RTEMS_SELF);
+ }
+
+ /*
+ * call any line discipline start function
+ */
+ if (rtems_termios_linesw[tty->t_line].l_start != NULL) {
+ rtems_termios_linesw[tty->t_line].l_start(tty);
+ }
+
+ /*
+ * try to push further characters to device
+ */
+ rtems_termios_refill_transmitter(tty);
+ }
+}
+
+/*
+ * this task actually processes any receive events
+ */
+static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
+{
+ struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+ rtems_event_set the_event;
+ int c;
+ char c_buf;
+
+ while (1) {
+ /*
+ * wait for rtems event
+ */
+ rtems_event_receive(
+ (TERMIOS_RX_PROC_EVENT | TERMIOS_RX_TERMINATE_EVENT),
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &the_event
+ );
+ if ((the_event & TERMIOS_RX_TERMINATE_EVENT) != 0) {
+ tty->rxTaskId = 0;
+ rtems_task_delete(RTEMS_SELF);
+ }
+
+ /*
+ * do something
+ */
+ c = tty->device.pollRead(tty->minor);
+ if (c != EOF) {
+ /*
+ * pollRead did call enqueue on its own
+ */
+ c_buf = c;
+ rtems_termios_enqueue_raw_characters ( tty,&c_buf,1);
+ }
+ }
+}
diff --git a/cpukit/libcsupport/src/termios_baud2index.c b/cpukit/libcsupport/src/termios_baud2index.c
new file mode 100644
index 0000000000..8bd6b867b8
--- /dev/null
+++ b/cpukit/libcsupport/src/termios_baud2index.c
@@ -0,0 +1,50 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/termios.h>
+#include <rtems/termiostypes.h>
+
+int rtems_termios_baud_to_index(
+ rtems_termios_baud_t termios_baud
+)
+{
+ int baud_index;
+
+ switch (termios_baud) {
+ case B0: baud_index = 0; break;
+ case B50: baud_index = 1; break;
+ case B75: baud_index = 2; break;
+ case B110: baud_index = 3; break;
+ case B134: baud_index = 4; break;
+ case B150: baud_index = 5; break;
+ case B200: baud_index = 6; break;
+ case B300: baud_index = 7; break;
+ case B600: baud_index = 8; break;
+ case B1200: baud_index = 9; break;
+ case B1800: baud_index = 10; break;
+ case B2400: baud_index = 11; break;
+ case B4800: baud_index = 12; break;
+ case B9600: baud_index = 13; break;
+ case B19200: baud_index = 14; break;
+ case B38400: baud_index = 15; break;
+ case B57600: baud_index = 16; break;
+ case B115200: baud_index = 17; break;
+ case B230400: baud_index = 18; break;
+ case B460800: baud_index = 19; break;
+ default: baud_index = -1; break;
+ }
+
+ return baud_index;
+}
diff --git a/cpukit/libcsupport/src/termios_baud2num.c b/cpukit/libcsupport/src/termios_baud2num.c
new file mode 100644
index 0000000000..57b908ebee
--- /dev/null
+++ b/cpukit/libcsupport/src/termios_baud2num.c
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/termios.h>
+#include <rtems/termiostypes.h>
+#include <rtems/assoc.h>
+
+extern rtems_assoc_t termios_assoc_table[];
+
+int32_t rtems_termios_baud_to_number(
+ int termios_baud
+)
+{
+ int baud;
+
+ baud = rtems_assoc_local_by_remote( termios_assoc_table, termios_baud );
+ if ( baud == 0 && termios_baud != 0 )
+ return -1;
+
+ return baud;
+}
diff --git a/cpukit/libcsupport/src/termios_baudtable.c b/cpukit/libcsupport/src/termios_baudtable.c
new file mode 100644
index 0000000000..92d1c6b809
--- /dev/null
+++ b/cpukit/libcsupport/src/termios_baudtable.c
@@ -0,0 +1,42 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/termios.h>
+#include <rtems/termiostypes.h>
+#include <rtems/assoc.h>
+
+rtems_assoc_t termios_assoc_table[] = {
+ { "B0", 0, B0 },
+ { "B50", 50, B50 },
+ { "B75", 75, B75 },
+ { "B110", 110, B110 },
+ { "B134", 134, B134 },
+ { "B150", 150, B150 },
+ { "B200", 200, B200 },
+ { "B300", 300, B300 },
+ { "B600", 600, B600 },
+ { "B1200", 1200, B1200 },
+ { "B1800", 1800, B1800 },
+ { "B2400", 2400, B2400 },
+ { "B4800", 4800, B4800 },
+ { "B9600", 9600, B9600 },
+ { "B19200", 19200, B19200 },
+ { "B38400", 38400, B38400 },
+ { "B57600", 57600, B57600 },
+ { "B115200", 115200, B115200 },
+ { "B230400", 230400, B230400 },
+ { "B460800", 460800, B460800 },
+ { NULL, 0, 0 }
+};
diff --git a/cpukit/libcsupport/src/termios_num2baud.c b/cpukit/libcsupport/src/termios_num2baud.c
new file mode 100644
index 0000000000..3725609135
--- /dev/null
+++ b/cpukit/libcsupport/src/termios_num2baud.c
@@ -0,0 +1,32 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/termios.h>
+#include <rtems/termiostypes.h>
+#include <rtems/assoc.h>
+
+extern rtems_assoc_t termios_assoc_table[];
+
+int rtems_termios_number_to_baud(
+ int32_t baud
+)
+{
+ int termios_baud;
+
+ termios_baud = rtems_assoc_remote_by_local( termios_assoc_table, baud );
+ if ( termios_baud == 0 && baud != 0 )
+ return -1;
+ return termios_baud;
+}
diff --git a/cpukit/libcsupport/src/termios_setinitialbaud.c b/cpukit/libcsupport/src/termios_setinitialbaud.c
new file mode 100644
index 0000000000..282f5533de
--- /dev/null
+++ b/cpukit/libcsupport/src/termios_setinitialbaud.c
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/termios.h>
+#include <rtems/termiostypes.h>
+
+int rtems_termios_set_initial_baud(
+ struct rtems_termios_tty *ttyp,
+ int32_t baud
+)
+{
+ int cflags_baud;
+
+ cflags_baud = rtems_termios_number_to_baud(baud);
+ if ( cflags_baud == -1 )
+ return -1;
+
+ ttyp->termios.c_cflag = (ttyp->termios.c_cflag & ~CBAUD) | cflags_baud;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/termiosinitialize.c b/cpukit/libcsupport/src/termiosinitialize.c
new file mode 100644
index 0000000000..b6660fe342
--- /dev/null
+++ b/cpukit/libcsupport/src/termiosinitialize.c
@@ -0,0 +1,54 @@
+/*
+ * Termios initialization routine
+ *
+ * Author:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+struct rtems_termios_tty *rtems_termios_ttyHead;
+struct rtems_termios_tty *rtems_termios_ttyTail;
+rtems_id rtems_termios_ttyMutex;
+
+void
+rtems_termios_initialize (void)
+{
+ rtems_status_code sc;
+
+ /*
+ * Create the mutex semaphore for the tty list
+ */
+ if (!rtems_termios_ttyMutex) {
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'm', 'i'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_termios_ttyMutex);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+}
diff --git a/cpukit/libcsupport/src/truncate.c b/cpukit/libcsupport/src/truncate.c
new file mode 100644
index 0000000000..7a0a98b4bd
--- /dev/null
+++ b/cpukit/libcsupport/src/truncate.c
@@ -0,0 +1,43 @@
+/*
+ * 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-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/cpukit/libcsupport/src/ttyname.c b/cpukit/libcsupport/src/ttyname.c
new file mode 100644
index 0000000000..ed0b5cbdc1
--- /dev/null
+++ b/cpukit/libcsupport/src/ttyname.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The 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.
+ */
+
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_TTYNAME
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <termios.h>
+#include <unistd.h>
+#include <string.h>
+#include <paths.h>
+#include <_syslist.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+static char ttyname_buf[sizeof (_PATH_DEV) + MAXNAMLEN];
+
+/*
+ * ttyname_r() - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
+ */
+int ttyname_r(
+ int fd,
+ char *name,
+ size_t namesize
+)
+{
+ struct stat sb;
+ struct termios tty;
+ struct dirent *dirp;
+ DIR *dp;
+ struct stat dsb;
+ char *rval;
+
+ /* Must be a terminal. */
+ if (tcgetattr (fd, &tty) < 0)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ /* Must be a character device. */
+ if (fstat (fd, &sb) || !S_ISCHR (sb.st_mode))
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ if ((dp = opendir (_PATH_DEV)) == NULL)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ /* Place the base directory in the path. */
+ strncpy (name, _PATH_DEV, namesize);
+
+ for (rval = NULL; (dirp = readdir (dp)) != NULL ;)
+ {
+ if (dirp->d_ino != sb.st_ino)
+ continue;
+ strcpy (name + sizeof (_PATH_DEV) - 1, dirp->d_name);
+ if (stat (name, &dsb) || sb.st_dev != dsb.st_dev ||
+ sb.st_ino != dsb.st_ino)
+ continue;
+ rval = name;
+ break;
+ }
+ (void) closedir (dp);
+ return 0;
+}
+
+/*
+ * ttyname() - POSIX 1003.1b 4.7.2 - Determine Terminal Device Name
+ */
+
+char *ttyname(
+ int fd
+)
+{
+ if ( !ttyname_r( fd, ttyname_buf, sizeof(ttyname_buf) ) )
+ return ttyname_buf;
+ return NULL;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/umask.c b/cpukit/libcsupport/src/umask.c
new file mode 100644
index 0000000000..32bf79e2b9
--- /dev/null
+++ b/cpukit/libcsupport/src/umask.c
@@ -0,0 +1,33 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/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/cpukit/libcsupport/src/unlink.c b/cpukit/libcsupport/src/unlink.c
new file mode 100644
index 0000000000..bb28959b6d
--- /dev/null
+++ b/cpukit/libcsupport/src/unlink.c
@@ -0,0 +1,103 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int unlink(
+ const char *path
+)
+{
+ int parentpathlen;
+ const char *name;
+ rtems_filesystem_location_info_t parentloc;
+ rtems_filesystem_location_info_t loc;
+ int i;
+ int result;
+ bool free_parentloc = false;
+
+ /*
+ * Get the node to be unlinked. Find the parent path first.
+ */
+
+ parentpathlen = rtems_filesystem_dirname ( path );
+
+ if ( parentpathlen == 0 )
+ rtems_filesystem_get_start_loc( path, &i, &parentloc );
+ else {
+ result = rtems_filesystem_evaluate_path( path, parentpathlen,
+ RTEMS_LIBIO_PERMS_WRITE,
+ &parentloc,
+ false );
+ if ( result != 0 )
+ return -1;
+
+ free_parentloc = true;
+ }
+
+ /*
+ * Start from the parent to find the node that should be under it.
+ */
+
+ loc = parentloc;
+ name = path + parentpathlen;
+ name += rtems_filesystem_prefix_separators( name, strlen( name ) );
+
+ result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
+ 0, &loc, false );
+ if ( result != 0 ) {
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+ return -1;
+ }
+
+ if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_freenode( &loc );
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+ rtems_set_errno_and_return_minus_one( EISDIR );
+ }
+
+ result = (*loc.ops->unlink_h)( &parentloc, &loc );
+
+ rtems_filesystem_freenode( &loc );
+ if ( free_parentloc )
+ rtems_filesystem_freenode( &parentloc );
+
+ return result;
+}
+
+/*
+ * _unlink_r
+ *
+ * This is the Newlib dependent reentrant version of unlink().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _unlink_r(
+ struct _reent *ptr __attribute__((unused)),
+ const char *path
+)
+{
+ return unlink( path );
+}
+#endif
diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c
new file mode 100644
index 0000000000..a2c67f7098
--- /dev/null
+++ b/cpukit/libcsupport/src/unmount.c
@@ -0,0 +1,162 @@
+/*
+ * 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-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include <rtems/chain.h>
+
+static bool is_fs_below_mount_point(
+ const rtems_filesystem_mount_table_entry_t *mt_entry,
+ void *arg
+)
+{
+ return arg == mt_entry->mt_point_node.mt_entry;
+}
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_location_info_t *fs_root_loc;
+ rtems_filesystem_location_info_t *fs_mount_loc;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+
+ /*
+ * Get
+ * The root node of the mounted filesytem.
+ * The node for the directory that the fileystem is mounted on.
+ * The mount entry that is being refered to.
+ */
+
+ if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) )
+ return -1;
+
+ mt_entry = loc.mt_entry;
+ fs_mount_loc = &mt_entry->mt_point_node;
+ fs_root_loc = &mt_entry->mt_fs_root;
+
+ /*
+ * Verify this is the root node for the file system to be unmounted.
+ */
+
+ if ( fs_root_loc->node_access != loc.node_access ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EACCES );
+ }
+
+ /*
+ * Free the loc node and just use the nodes from the mt_entry .
+ */
+
+ rtems_filesystem_freenode( &loc );
+
+ /*
+ * Verify the current node is not in this filesystem.
+ * XXX - Joel I have a question here wasn't code added
+ * that made the current node thread based instead
+ * of system based? I thought it was but it doesn't
+ * look like it in this version.
+ */
+
+ if ( rtems_filesystem_current.mt_entry == mt_entry )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Verify there are no file systems below the path specified
+ */
+
+ if ( rtems_filesystem_mount_iterate( is_fs_below_mount_point,
+ fs_root_loc->mt_entry ) )
+ rtems_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( mt_entry ) == 1 )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being unmounted on to do its cleanup.
+ * If it fails it will set the errno to the approprate value
+ * and the fileystem will not be modified.
+ */
+
+ if (( fs_mount_loc->ops->unmount_h )( mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the mounted filesystem to unmark the use of the root node.
+ *
+ * Run the unmount function for the subordinate file system.
+ *
+ * If we fail to unmount the filesystem remount it on the base filesystems
+ * directory node.
+ *
+ * NOTE: Fatal error is called in a case which should never happen
+ * This was response was questionable but the best we could
+ * come up with.
+ */
+
+ if ((fs_root_loc->ops->fsunmount_me_h )( mt_entry ) != 0){
+ if (( fs_mount_loc->ops->mount_h )( mt_entry ) != 0 )
+ rtems_fatal_error_occurred( 0 );
+ return -1;
+ }
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ rtems_libio_lock();
+ rtems_chain_extract( &mt_entry->Node );
+ rtems_libio_unlock();
+
+ /*
+ * Free the memory node that was allocated in mount
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ rtems_filesystem_freenode( fs_mount_loc );
+ free( mt_entry );
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/utime.c b/cpukit/libcsupport/src/utime.c
new file mode 100644
index 0000000000..25bcb0761b
--- /dev/null
+++ b/cpukit/libcsupport/src/utime.c
@@ -0,0 +1,47 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int result;
+ struct utimbuf now;
+
+ if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &temp_loc, true ) )
+ return -1;
+
+ if ( times == NULL ) {
+ now.actime = now.modtime = time( NULL );
+ times = &now;
+ }
+
+ result = (*temp_loc.ops->utime_h)( &temp_loc, times->actime, times->modtime );
+
+ rtems_filesystem_freenode( &temp_loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/utimes.c b/cpukit/libcsupport/src/utimes.c
new file mode 100644
index 0000000000..b2070a9431
--- /dev/null
+++ b/cpukit/libcsupport/src/utimes.c
@@ -0,0 +1,33 @@
+/*
+ * Written by: Vinu Rajashekhar <vinutheraj@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/time.h>
+
+int utimes(
+ const char *path,
+ const struct timeval times[2]
+)
+{
+ struct utimbuf timeinsecs;
+
+ if ( times == NULL )
+ return utime( path, NULL );
+
+ timeinsecs.actime = (time_t) times[0].tv_sec;
+ timeinsecs.modtime = (time_t) times[1].tv_sec;
+
+ return utime( path, &timeinsecs );
+}
diff --git a/cpukit/libcsupport/src/utsname.c b/cpukit/libcsupport/src/utsname.c
new file mode 100644
index 0000000000..564a762942
--- /dev/null
+++ b/cpukit/libcsupport/src/utsname.c
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <inttypes.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.4.1 Get System Name, P1003.1b-1993, p. 90
+ */
+
+int uname(
+ struct utsname *name
+)
+{
+ /* XXX: Here is what Solaris returns...
+ sysname = SunOS
+ nodename = node_name
+ release = 5.3
+ version = Generic_101318-12
+ machine = sun4m
+ */
+
+ if ( !name )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ strncpy( name->sysname, "RTEMS", sizeof(name->sysname) );
+
+ snprintf( name->nodename, sizeof(name->nodename), "Node %" PRId16, _Objects_Local_node );
+
+ strncpy( name->release, RTEMS_VERSION, sizeof(name->release) );
+
+ strncpy( name->version, "", sizeof(name->version) );
+
+ snprintf( name->machine, sizeof(name->machine), "%s/%s", CPU_NAME, CPU_MODEL_NAME );
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/vprintk.c b/cpukit/libcsupport/src/vprintk.c
new file mode 100644
index 0000000000..852b5e302f
--- /dev/null
+++ b/cpukit/libcsupport/src/vprintk.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 1997 -
+ * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+ *
+ * http://pandora.ist.utl.pt
+ *
+ * Instituto Superior Tecnico * Lisboa * PORTUGAL
+ *
+ * Disclaimer:
+ *
+ * This file is provided "AS IS" without warranty of any kind, either
+ * expressed or implied.
+ *
+ * This code is based on code by: Jose Rufino - IST
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <rtems/bspIo.h>
+
+static void printNum(
+ long num,
+ unsigned base,
+ bool sign,
+ unsigned maxwidth,
+ char lead
+);
+
+/*
+ * vprintk
+ *
+ * A simplified version of printf intended for use when the
+ * console is not yet initialized or in ISR's.
+ *
+ * Arguments:
+ * as in printf: fmt - format string, ... - unnamed arguments.
+ */
+void vprintk(
+ const char *fmt,
+ va_list ap
+)
+{
+ for (; *fmt != '\0'; fmt++) {
+ unsigned base = 0;
+ unsigned width = 0;
+ bool lflag = false;
+ bool minus = false;
+ bool sign = false;
+ char lead = ' ';
+ char c;
+
+ if (*fmt != '%') {
+ BSP_output_char(*fmt);
+ continue;
+ }
+ fmt++;
+ if (*fmt == '0' ) {
+ lead = '0';
+ fmt++;
+ }
+ if (*fmt == '-' ) {
+ minus = true;
+ fmt++;
+ }
+ while (*fmt >= '0' && *fmt <= '9' ) {
+ width *= 10;
+ width += ((unsigned) *fmt - '0');
+ fmt++;
+ }
+
+ if ((c = *fmt) == 'l') {
+ lflag = true;
+ c = *++fmt;
+ }
+ if ( c == 'c' ) {
+ /* need a cast here since va_arg() only takes fully promoted types */
+ char chr = (char) va_arg(ap, int);
+ BSP_output_char(chr);
+ continue;
+ }
+ if ( c == 's' ) {
+ unsigned i, len;
+ char *s, *str;
+
+ str = va_arg(ap, char *);
+
+ if ( str == NULL ) {
+ str = "";
+ }
+
+ /* calculate length of string */
+ for ( len=0, s=str ; *s ; len++, s++ )
+ ;
+
+ /* leading spaces */
+ if ( !minus )
+ for ( i=len ; i<width ; i++ )
+ BSP_output_char(' ');
+
+ /* no width option */
+ if (width == 0) {
+ width = len;
+ }
+
+ /* output the string */
+ for ( i=0 ; i<width && *str ; str++ )
+ BSP_output_char(*str);
+
+ /* trailing spaces */
+ if ( minus )
+ for ( i=len ; i<width ; i++ )
+ BSP_output_char(' ');
+
+ continue;
+ }
+
+ /* must be a numeric format or something unsupported */
+ if ( c == 'o' || c == 'O' ) {
+ base = 8; sign = false;
+ } else if ( c == 'i' || c == 'I' ||
+ c == 'd' || c == 'D' ) {
+ base = 10; sign = true;
+ } else if ( c == 'u' || c == 'U' ) {
+ base = 10; sign = false;
+ } else if ( c == 'x' || c == 'X' ) {
+ base = 16; sign = false;
+ } else if ( c == 'p' ) {
+ base = 16; sign = false; lflag = true;
+ } else {
+ BSP_output_char(c);
+ continue;
+ }
+
+ printNum(
+ lflag ? va_arg(ap, long) : (long) va_arg(ap, int),
+ base,
+ sign,
+ width,
+ lead
+ );
+ }
+}
+
+/*
+ * printNum - print number in a given base.
+ * Arguments
+ * num - number to print
+ * base - base used to print the number.
+ */
+static void printNum(
+ long num,
+ unsigned base,
+ bool sign,
+ unsigned maxwidth,
+ char lead
+)
+{
+ unsigned long unsigned_num;
+ unsigned long n;
+ unsigned count;
+ char toPrint[20];
+
+ if ( sign && (num < 0) ) {
+ BSP_output_char('-');
+ unsigned_num = (unsigned long) -num;
+ if (maxwidth) maxwidth--;
+ } else {
+ unsigned_num = (unsigned long) num;
+ }
+
+ count = 0;
+ while ((n = unsigned_num / base) > 0) {
+ toPrint[count++] = (char) (unsigned_num - (n * base));
+ unsigned_num = n;
+ }
+ toPrint[count++] = (char) unsigned_num;
+
+ for (n=maxwidth ; n > count; n-- )
+ BSP_output_char(lead);
+
+ for (n = 0; n < count; n++) {
+ BSP_output_char("0123456789ABCDEF"[(int)(toPrint[count-(n+1)])]);
+ }
+}
diff --git a/cpukit/libcsupport/src/write.c b/cpukit/libcsupport/src/write.c
new file mode 100644
index 0000000000..b723f426b6
--- /dev/null
+++ b/cpukit/libcsupport/src/write.c
@@ -0,0 +1,53 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+ssize_t write(
+ int fd,
+ const void *buffer,
+ size_t count
+)
+{
+ ssize_t rc;
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open( iop );
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the write() request.
+ */
+ rc = (*iop->pathinfo.handlers->write_h)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
diff --git a/cpukit/libcsupport/src/write_r.c b/cpukit/libcsupport/src/write_r.c
new file mode 100644
index 0000000000..ad142a7364
--- /dev/null
+++ b/cpukit/libcsupport/src/write_r.c
@@ -0,0 +1,40 @@
+/*
+ * write_r() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _write_r(
+ struct _reent *ptr __attribute__((unused)),
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libcsupport/src/writev.c b/cpukit/libcsupport/src/writev.c
new file mode 100644
index 0000000000..380e325365
--- /dev/null
+++ b/cpukit/libcsupport/src/writev.c
@@ -0,0 +1,128 @@
+/*
+ * writev() - POSIX 1003.1 - Read a Vector
+ *
+ * OpenGroup URL:
+ *
+ * http://www.opengroup.org/onlinepubs/009695399/functions/writev.html
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+ssize_t writev(
+ int fd,
+ const struct iovec *iov,
+ int iovcnt
+)
+{
+ ssize_t total;
+ int v;
+ int bytes;
+ rtems_libio_t *iop;
+ ssize_t old;
+ bool all_zeros;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open( iop );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Argument validation on IO vector
+ */
+ if ( !iov )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iovcnt <= 0 )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iovcnt > IOV_MAX )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * OpenGroup says that you are supposed to return EINVAL if the
+ * sum of the iov_len values in the iov array would overflow a
+ * ssize_t.
+ *
+ * Also we would like to ensure that no IO is performed if there
+ * are obvious errors in the iovec. So this extra loop ensures
+ * that we do not do anything if there is an argument error.
+ *
+ * In addition,the OpenGroup specification says that if all the
+ * iov_len entries are zero, then the call has no effect. So
+ * this loop does that check as well and sets "all-zero" appropriately.
+ * The variable "all_zero" is used as an early exit point before
+ * entering the write loop.
+ */
+ all_zeros = true;
+ for ( old=0, total=0, v=0 ; v < iovcnt ; v++ ) {
+
+ /*
+ * iov[v].iov_len cannot be less than 0 because size_t is unsigned.
+ * So we only check for zero.
+ */
+ if ( iov[v].iov_base == 0 )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( iov[v].iov_len )
+ all_zeros = false;
+
+ /* check for wrap */
+ old = total;
+ total += iov[v].iov_len;
+ if ( total < old || total > SSIZE_MAX )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * A writev with all zeros is supposed to have no effect per OpenGroup.
+ */
+ if ( all_zeros == true ) {
+ return 0;
+ }
+
+ /*
+ * Now process the writev().
+ */
+ for ( total=0, v=0 ; v < iovcnt ; v++ ) {
+ /* all zero lengths has no effect */
+ if ( iov[v].iov_len == 0 )
+ continue;
+
+ bytes = (*iop->pathinfo.handlers->write_h)(
+ iop,
+ iov[v].iov_base,
+ iov[v].iov_len
+ );
+
+ if ( bytes < 0 )
+ return -1;
+
+ if ( bytes > 0 ) {
+ iop->offset += bytes;
+ total += bytes;
+ }
+
+ if (bytes != iov[ v ].iov_len)
+ break;
+ }
+
+ return total;
+}
+