summaryrefslogtreecommitdiff
path: root/components/libc
diff options
context:
space:
mode:
Diffstat (limited to 'components/libc')
-rw-r--r--components/libc/Kconfig12
-rw-r--r--components/libc/compilers/common/SConscript7
-rw-r--r--components/libc/compilers/common/readme.md11
-rw-r--r--components/libc/compilers/common/unistd.c119
-rw-r--r--components/libc/posix/aio/SConscript4
-rw-r--r--components/libc/posix/getline/SConscript2
-rw-r--r--components/libc/posix/mmap/SConscript2
-rw-r--r--components/libc/posix/pthreads/SConscript2
-rw-r--r--components/libc/posix/signal/SConscript2
-rw-r--r--components/libc/posix/src/SConscript10
-rw-r--r--components/libc/posix/src/delay.c (renamed from components/libc/compilers/common/delay.c)9
-rw-r--r--components/libc/posix/src/poll.c230
-rw-r--r--components/libc/posix/src/select.c180
-rw-r--r--components/libc/posix/src/unistd.c1044
-rw-r--r--components/libc/posix/termios/SConscript2
15 files changed, 1490 insertions, 146 deletions
diff --git a/components/libc/Kconfig b/components/libc/Kconfig
index b9600ef389..812b1ce48c 100644
--- a/components/libc/Kconfig
+++ b/components/libc/Kconfig
@@ -2,6 +2,8 @@ menu "POSIX layer and C standard library"
config RT_USING_LIBC
bool "Enable libc APIs from toolchain"
+ select RT_USING_DFS
+ select RT_USING_POSIX
default y
config RT_USING_PTHREADS
@@ -14,9 +16,9 @@ if RT_USING_PTHREADS
default 8
endif
-if RT_USING_LIBC && RT_USING_DFS
+if RT_USING_DFS
config RT_USING_POSIX
- bool "Enable POSIX layer for compatibility with UNIX APIs, poll/select etc"
+ bool "Enable POSIX layer, open/read/write/select etc"
select RT_USING_DFS_DEVFS
default y
@@ -49,9 +51,9 @@ if RT_USING_LIBC
default n
if RT_USING_MODULE
- config RT_USING_CUSTOM_DLMODULE
- bool "Enable load dynamic module by custom"
- default n
+ config RT_USING_CUSTOM_DLMODULE
+ bool "Enable load dynamic module by custom"
+ default n
endif
endif
diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript
index fbdb2f11ec..b7a6626a36 100644
--- a/components/libc/compilers/common/SConscript
+++ b/components/libc/compilers/common/SConscript
@@ -6,18 +6,15 @@ src = []
cwd = GetCurrentDir()
group = []
CPPPATH = [cwd]
+CPPDEFINES = []
if GetDepend('RT_USING_LIBC'):
src += Glob('*.c')
- if GetDepend('RT_USING_POSIX') == False:
- SrcRemove(src, ['unistd.c', 'delay.c'])
elif GetDepend('RT_LIBC_USING_TIME'):
src += Glob('time.c')
if rtconfig.CROSS_TOOL == 'keil':
- CPPDEFINES = ['__CLK_TCK=RT_TICK_PER_SECOND']
-else:
- CPPDEFINES = []
+ CPPDEFINES += ['__CLK_TCK=RT_TICK_PER_SECOND']
group = DefineGroup('libc', src, depend = [], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
diff --git a/components/libc/compilers/common/readme.md b/components/libc/compilers/common/readme.md
index 856ddeb045..82e23f8970 100644
--- a/components/libc/compilers/common/readme.md
+++ b/components/libc/compilers/common/readme.md
@@ -1,10 +1 @@
-## Attentions
-
-1. This folder is "common" for all toolchains.
-
-2. If you want to add new `.c` files, please do not forget to fix SConscript file too. eg:
-
-```python
-if GetDepend('RT_USING_POSIX') == False:
- SrcRemove(src, ['unistd.c'])
-``` \ No newline at end of file
+This folder is "common" for all toolchains. \ No newline at end of file
diff --git a/components/libc/compilers/common/unistd.c b/components/libc/compilers/common/unistd.c
deleted file mode 100644
index 9a457c4200..0000000000
--- a/components/libc/compilers/common/unistd.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-09-01 Meco Man first Version
- * 2021-02-12 Meco Man move all functions located in <pthread_sleep.c> to this file
- */
-
-#include <unistd.h>
-#include <rtthread.h>
-#include <rthw.h>
-
-#ifdef RT_USING_POSIX_TERMIOS
-#include "termios.h"
-int isatty(int fd)
-{
- struct termios ts;
- return(tcgetattr(fd, &ts) != -1); /*true if no error (is a tty)*/
-}
-#else
-int isatty(int fd)
-{
- if (fd >=0 && fd < 3)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-#endif
-RTM_EXPORT(isatty);
-
-char *ttyname(int fd)
-{
- return "/dev/tty"; /* TODO: need to add more specific */
-}
-RTM_EXPORT(ttyname);
-
-unsigned int sleep(unsigned int seconds)
-{
- if (rt_thread_self() != RT_NULL)
- {
- rt_thread_delay(seconds * RT_TICK_PER_SECOND);
- }
- else /* scheduler has not run yet */
- {
- while(seconds > 0)
- {
- rt_hw_us_delay(1000000u);
- seconds --;
- }
- }
-
- return 0;
-}
-RTM_EXPORT(sleep);
-
-int usleep(useconds_t usec)
-{
- if (rt_thread_self() != RT_NULL)
- {
- rt_thread_mdelay(usec / 1000u);
- }
- else /* scheduler has not run yet */
- {
- rt_hw_us_delay(usec / 1000u);
- }
- rt_hw_us_delay(usec % 1000u);
-
- return 0;
-}
-RTM_EXPORT(usleep);
-
-pid_t gettid(void)
-{
- /*TODO*/
- return 0;
-}
-
-pid_t getpid(void)
-{
- return gettid();
-}
-RTM_EXPORT(getpid);
-
-pid_t getppid(void)
-{
- return 0;
-}
-RTM_EXPORT(getppid);
-
-uid_t getuid(void)
-{
- return 0; /*ROOT*/
-}
-RTM_EXPORT(getuid);
-
-uid_t geteuid(void)
-{
- return 0; /*ROOT*/
-}
-RTM_EXPORT(geteuid);
-
-gid_t getgid(void)
-{
- return 0; /*ROOT*/
-}
-RTM_EXPORT(getgid);
-
-gid_t getegid(void)
-{
- return 0; /*ROOT*/
-}
-RTM_EXPORT(getegid);
diff --git a/components/libc/posix/aio/SConscript b/components/libc/posix/aio/SConscript
index f10462e9c4..445efaade5 100644
--- a/components/libc/posix/aio/SConscript
+++ b/components/libc/posix/aio/SConscript
@@ -3,9 +3,9 @@
from building import *
cwd = GetCurrentDir()
-src = Glob('*.c') + Glob('*.cpp')
+src = Glob('*.c')
CPPPATH = [cwd]
-group = DefineGroup('libc', src, depend = ['RT_USING_POSIX', 'RT_USING_POSIX_AIO'], CPPPATH = CPPPATH)
+group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX', 'RT_USING_POSIX_AIO'], CPPPATH = CPPPATH)
Return('group')
diff --git a/components/libc/posix/getline/SConscript b/components/libc/posix/getline/SConscript
index fa4c8618c1..bb18dc04c5 100644
--- a/components/libc/posix/getline/SConscript
+++ b/components/libc/posix/getline/SConscript
@@ -6,7 +6,7 @@ cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
-group = DefineGroup('libc', src,
+group = DefineGroup('POSIX', src,
depend = ['RT_USING_LIBC', 'RT_USING_POSIX','RT_USING_POSIX_GETLINE'],
CPPPATH = CPPPATH)
diff --git a/components/libc/posix/mmap/SConscript b/components/libc/posix/mmap/SConscript
index 1a36a15710..fd5b2b953e 100644
--- a/components/libc/posix/mmap/SConscript
+++ b/components/libc/posix/mmap/SConscript
@@ -6,7 +6,7 @@ cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
-group = DefineGroup('libc', src,
+group = DefineGroup('POSIX', src,
depend = ['RT_USING_DFS', 'RT_USING_POSIX_MMAP'],
CPPPATH = CPPPATH)
diff --git a/components/libc/posix/pthreads/SConscript b/components/libc/posix/pthreads/SConscript
index 767b406d4c..7cd78300b2 100644
--- a/components/libc/posix/pthreads/SConscript
+++ b/components/libc/posix/pthreads/SConscript
@@ -16,7 +16,7 @@ try:
except :
pass
-group = DefineGroup('libc', src,
+group = DefineGroup('POSIX', src,
depend = ['RT_USING_PTHREADS', 'RT_USING_LIBC'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')
diff --git a/components/libc/posix/signal/SConscript b/components/libc/posix/signal/SConscript
index f07ff58f6e..07cd98cbe0 100644
--- a/components/libc/posix/signal/SConscript
+++ b/components/libc/posix/signal/SConscript
@@ -6,7 +6,7 @@ cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
-group = DefineGroup('libc', src,
+group = DefineGroup('POSIX', src,
depend = ['RT_USING_SIGNALS', 'RT_USING_PTHREADS', 'RT_USING_LIBC'],
CPPPATH = CPPPATH)
diff --git a/components/libc/posix/src/SConscript b/components/libc/posix/src/SConscript
new file mode 100644
index 0000000000..5640181ac5
--- /dev/null
+++ b/components/libc/posix/src/SConscript
@@ -0,0 +1,10 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX'])
+
+Return('group')
diff --git a/components/libc/compilers/common/delay.c b/components/libc/posix/src/delay.c
index 4666258d3b..1638caafbf 100644
--- a/components/libc/compilers/common/delay.c
+++ b/components/libc/posix/src/delay.c
@@ -9,6 +9,15 @@
*/
#include <rtthread.h>
#include <rthw.h>
+#define DBG_TAG "POSIX.delay"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+RT_WEAK void rt_hw_us_delay(rt_uint32_t us)
+{
+ (void) us;
+ LOG_W("Please consider implementing rt_hw_us_delay() in another file.");
+}
void msleep(unsigned int msecs)
{
diff --git a/components/libc/posix/src/poll.c b/components/libc/posix/src/poll.c
new file mode 100644
index 0000000000..2109fb310b
--- /dev/null
+++ b/components/libc/posix/src/poll.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2016-12-28 Bernard first version
+ * 2018-03-09 Bernard Add protection for pt->triggered.
+ */
+#include <stdint.h>
+#include <rthw.h>
+#include <rtthread.h>
+#include <dfs_file.h>
+#include <poll.h>
+
+#ifdef RT_USING_POSIX
+
+struct rt_poll_node;
+
+struct rt_poll_table
+{
+ rt_pollreq_t req;
+ rt_uint32_t triggered; /* the waited thread whether triggered */
+ rt_thread_t polling_thread;
+ struct rt_poll_node *nodes;
+};
+
+struct rt_poll_node
+{
+ struct rt_wqueue_node wqn;
+ struct rt_poll_table *pt;
+ struct rt_poll_node *next;
+};
+
+static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key)
+{
+ struct rt_poll_node *pn;
+
+ if (key && !((rt_ubase_t)key & wait->key))
+ return -1;
+
+ pn = rt_container_of(wait, struct rt_poll_node, wqn);
+ pn->pt->triggered = 1;
+
+ return __wqueue_default_wake(wait, key);
+}
+
+static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
+{
+ struct rt_poll_table *pt;
+ struct rt_poll_node *node;
+
+ node = (struct rt_poll_node *)rt_malloc(sizeof(struct rt_poll_node));
+ if (node == RT_NULL)
+ return;
+
+ pt = rt_container_of(req, struct rt_poll_table, req);
+
+ node->wqn.key = req->_key;
+ rt_list_init(&(node->wqn.list));
+ node->wqn.polling_thread = pt->polling_thread;
+ node->wqn.wakeup = __wqueue_pollwake;
+ node->next = pt->nodes;
+ node->pt = pt;
+ pt->nodes = node;
+ rt_wqueue_add(wq, &node->wqn);
+}
+
+static void poll_table_init(struct rt_poll_table *pt)
+{
+ pt->req._proc = _poll_add;
+ pt->triggered = 0;
+ pt->nodes = RT_NULL;
+ pt->polling_thread = rt_thread_self();
+}
+
+static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
+{
+ rt_int32_t timeout;
+ int ret = 0;
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ thread = pt->polling_thread;
+
+ timeout = rt_tick_from_millisecond(msec);
+
+ level = rt_hw_interrupt_disable();
+
+ if (timeout != 0 && !pt->triggered)
+ {
+ rt_thread_suspend(thread);
+ if (timeout > 0)
+ {
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ level = rt_hw_interrupt_disable();
+ }
+
+ ret = !pt->triggered;
+ rt_hw_interrupt_enable(level);
+
+ return ret;
+}
+
+static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req)
+{
+ int mask = 0;
+ int fd;
+
+ fd = pollfd->fd;
+
+ if (fd >= 0)
+ {
+ struct dfs_fd *f = fd_get(fd);
+ mask = POLLNVAL;
+
+ if (f)
+ {
+ mask = POLLMASK_DEFAULT;
+ if (f->fops->poll)
+ {
+ req->_key = pollfd->events | POLLERR | POLLHUP;
+
+ mask = f->fops->poll(f, req);
+
+ /* dealwith the device return error -1*/
+ if (mask < 0)
+ {
+ fd_put(f);
+ pollfd->revents = 0;
+ return mask;
+ }
+ }
+ /* Mask out unneeded events. */
+ mask &= pollfd->events | POLLERR | POLLHUP;
+ fd_put(f);
+ }
+ }
+ pollfd->revents = mask;
+
+ return mask;
+}
+
+static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec)
+{
+ int num;
+ int istimeout = 0;
+ int n;
+ struct pollfd *pf;
+ int ret = 0;
+
+ if (msec == 0)
+ {
+ pt->req._proc = RT_NULL;
+ istimeout = 1;
+ }
+
+ while (1)
+ {
+ pf = fds;
+ num = 0;
+
+ for (n = 0; n < nfds; n ++)
+ {
+ ret = do_pollfd(pf, &pt->req);
+ if(ret < 0)
+ {
+ /*dealwith the device return error -1 */
+ pt->req._proc = RT_NULL;
+ return ret;
+ }
+ else if(ret > 0)
+ {
+ num ++;
+ pt->req._proc = RT_NULL;
+ }
+ pf ++;
+ }
+
+ pt->req._proc = RT_NULL;
+
+ if (num || istimeout)
+ break;
+
+ if (poll_wait_timeout(pt, msec))
+ istimeout = 1;
+ }
+
+ return num;
+}
+
+static void poll_teardown(struct rt_poll_table *pt)
+{
+ struct rt_poll_node *node, *next;
+
+ next = pt->nodes;
+ while (next)
+ {
+ node = next;
+ rt_wqueue_remove(&node->wqn);
+ next = node->next;
+ rt_free(node);
+ }
+}
+
+int poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ int num;
+ struct rt_poll_table table;
+
+ poll_table_init(&table);
+
+ num = poll_do(fds, nfds, &table, timeout);
+
+ poll_teardown(&table);
+
+ return num;
+}
+
+#endif
diff --git a/components/libc/posix/src/select.c b/components/libc/posix/src/select.c
new file mode 100644
index 0000000000..25cda0f0d1
--- /dev/null
+++ b/components/libc/posix/src/select.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2016-12-28 Bernard first version
+ */
+#include <rtthread.h>
+#include <poll.h>
+#include <sys/select.h>
+
+#ifdef RT_USING_POSIX
+
+static void fdszero(fd_set *set, int nfds)
+{
+ fd_mask *m;
+ int n;
+
+ /*
+ The 'sizeof(fd_set)' of the system space may differ from user space,
+ so the actual size of the 'fd_set' is determined here with the parameter 'nfds'
+ */
+ m = (fd_mask *)set;
+ for (n = 0; n < nfds; n += (sizeof(fd_mask) * 8))
+ {
+ rt_memset(m, 0, sizeof(fd_mask));
+ m ++;
+ }
+}
+
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+ int fd;
+ int npfds;
+ int msec;
+ int ndx;
+ int ret;
+ struct pollfd *pollset = RT_NULL;
+
+ /* How many pollfd structures do we need to allocate? */
+ for (fd = 0, npfds = 0; fd < nfds; fd++)
+ {
+ /* Check if any monitor operation is requested on this fd */
+ if ((readfds && FD_ISSET(fd, readfds)) ||
+ (writefds && FD_ISSET(fd, writefds)) ||
+ (exceptfds && FD_ISSET(fd, exceptfds)))
+ {
+ npfds++;
+ }
+ }
+
+ /* Allocate the descriptor list for poll() */
+ if (npfds > 0)
+ {
+ pollset = (struct pollfd *)rt_calloc(npfds, sizeof(struct pollfd));
+ if (!pollset)
+ {
+ return -1;
+ }
+ }
+
+ /* Initialize the descriptor list for poll() */
+ for (fd = 0, ndx = 0; fd < nfds; fd++)
+ {
+ int incr = 0;
+
+ /* The readfs set holds the set of FDs that the caller can be assured
+ * of reading from without blocking. Note that POLLHUP is included as
+ * a read-able condition. POLLHUP will be reported at the end-of-file
+ * or when a connection is lost. In either case, the read() can then
+ * be performed without blocking.
+ */
+
+ if (readfds && FD_ISSET(fd, readfds))
+ {
+ pollset[ndx].fd = fd;
+ pollset[ndx].events |= POLLIN;
+ incr = 1;
+ }
+
+ if (writefds && FD_ISSET(fd, writefds))
+ {
+ pollset[ndx].fd = fd;
+ pollset[ndx].events |= POLLOUT;
+ incr = 1;
+ }
+
+ if (exceptfds && FD_ISSET(fd, exceptfds))
+ {
+ pollset[ndx].fd = fd;
+ incr = 1;
+ }
+
+ ndx += incr;
+ }
+
+ RT_ASSERT(ndx == npfds);
+
+ /* Convert the timeout to milliseconds */
+ if (timeout)
+ {
+ msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+ }
+ else
+ {
+ msec = -1;
+ }
+
+ /* Then let poll do all of the real work. */
+
+ ret = poll(pollset, npfds, msec);
+
+ /* Now set up the return values */
+ if (readfds)
+ {
+ fdszero(readfds, nfds);
+ }
+
+ if (writefds)
+ {
+ fdszero(writefds, nfds);
+ }
+
+ if (exceptfds)
+ {
+ fdszero(exceptfds, nfds);
+ }
+
+ /* Convert the poll descriptor list back into selects 3 bitsets */
+
+ if (ret > 0)
+ {
+ ret = 0;
+ for (ndx = 0; ndx < npfds; ndx++)
+ {
+ /* Check for read conditions. Note that POLLHUP is included as a
+ * read condition. POLLHUP will be reported when no more data will
+ * be available (such as when a connection is lost). In either
+ * case, the read() can then be performed without blocking.
+ */
+
+ if (readfds)
+ {
+ if (pollset[ndx].revents & (POLLIN | POLLHUP))
+ {
+ FD_SET(pollset[ndx].fd, readfds);
+ ret++;
+ }
+ }
+
+ /* Check for write conditions */
+ if (writefds)
+ {
+ if (pollset[ndx].revents & POLLOUT)
+ {
+ FD_SET(pollset[ndx].fd, writefds);
+ ret++;
+ }
+ }
+
+ /* Check for exceptions */
+ if (exceptfds)
+ {
+ if (pollset[ndx].revents & POLLERR)
+ {
+ FD_SET(pollset[ndx].fd, exceptfds);
+ ret++;
+ }
+ }
+ }
+ }
+
+ if (pollset) rt_free(pollset);
+
+ return ret;
+}
+
+#endif
diff --git a/components/libc/posix/src/unistd.c b/components/libc/posix/src/unistd.c
new file mode 100644
index 0000000000..ef2df2c2fe
--- /dev/null
+++ b/components/libc/posix/src/unistd.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-09-01 Meco Man first Version
+ * 2021-02-12 Meco Man move all functions located in <pthread_sleep.c> to this file
+ */
+#include <rtthread.h>
+#include <dfs_file.h>
+#include <dfs_private.h>
+#include <sys/errno.h>
+#include <unistd.h>
+#include <delay.h>
+
+/**
+ * this function is a POSIX compliant version, which will open a file and
+ * return a file descriptor according specified flags.
+ *
+ * @param file the path name of file.
+ * @param flags the file open flags.
+ *
+ * @return the non-negative integer on successful open, others for failed.
+ */
+int open(const char *file, int flags, ...)
+{
+ int fd, result;
+ struct dfs_fd *d;
+
+ /* allocate a fd */
+ fd = fd_new();
+ if (fd < 0)
+ {
+ rt_set_errno(-ENOMEM);
+
+ return -1;
+ }
+ d = fd_get(fd);
+
+ result = dfs_file_open(d, file, flags);
+ if (result < 0)
+ {
+ /* release the ref-count of fd */
+ fd_put(d);
+ fd_put(d);
+
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+
+ return fd;
+}
+RTM_EXPORT(open);
+
+/**
+ * this function is a POSIX compliant version, which will close the open
+ * file descriptor.
+ *
+ * @param fd the file descriptor.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int close(int fd)
+{
+ int result;
+ struct dfs_fd *d;
+
+ d = fd_get(fd);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ result = dfs_file_close(d);
+ fd_put(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ fd_put(d);
+
+ return 0;
+}
+RTM_EXPORT(close);
+
+/**
+ * this function is a POSIX compliant version, which will read specified data
+ * buffer length for an open file descriptor.
+ *
+ * @param fd the file descriptor.
+ * @param buf the buffer to save the read data.
+ * @param len the maximal length of data buffer
+ *
+ * @return the actual read data buffer length. If the returned value is 0, it
+ * may be reach the end of file, please check errno.
+ */
+#ifdef _READ_WRITE_RETURN_TYPE
+_READ_WRITE_RETURN_TYPE read(int fd, void *buf, size_t len) /* some gcc tool chains will use different data structure */
+#else
+ssize_t read(int fd, void *buf, size_t len)
+#endif
+{
+ int result;
+ struct dfs_fd *d;
+
+ /* get the fd */
+ d = fd_get(fd);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ result = dfs_file_read(d, buf, len);
+ if (result < 0)
+ {
+ fd_put(d);
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+
+ return result;
+}
+RTM_EXPORT(read);
+
+/**
+ * this function is a POSIX compliant version, which will write specified data
+ * buffer length for an open file descriptor.
+ *
+ * @param fd the file descriptor
+ * @param buf the data buffer to be written.
+ * @param len the data buffer length.
+ *
+ * @return the actual written data buffer length.
+ */
+#ifdef _READ_WRITE_RETURN_TYPE
+_READ_WRITE_RETURN_TYPE write(int fd, const void *buf, size_t len) /* some gcc tool chains will use different data structure */
+#else
+ssize_t write(int fd, const void *buf, size_t len)
+#endif
+{
+ int result;
+ struct dfs_fd *d;
+
+ /* get the fd */
+ d = fd_get(fd);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ result = dfs_file_write(d, buf, len);
+ if (result < 0)
+ {
+ fd_put(d);
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+
+ return result;
+}
+RTM_EXPORT(write);
+
+/**
+ * this function is a POSIX compliant version, which will seek the offset for
+ * an open file descriptor.
+ *
+ * @param fd the file descriptor.
+ * @param offset the offset to be seeked.
+ * @param whence the directory of seek.
+ *
+ * @return the current read/write position in the file, or -1 on failed.
+ */
+off_t lseek(int fd, off_t offset, int whence)
+{
+ int result;
+ struct dfs_fd *d;
+
+ d = fd_get(fd);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+
+ case SEEK_CUR:
+ offset += d->pos;
+ break;
+
+ case SEEK_END:
+ offset += d->size;
+ break;
+
+ default:
+ fd_put(d);
+ rt_set_errno(-EINVAL);
+
+ return -1;
+ }
+
+ if (offset < 0)
+ {
+ fd_put(d);
+ rt_set_errno(-EINVAL);
+
+ return -1;
+ }
+ result = dfs_file_lseek(d, offset);
+ if (result < 0)
+ {
+ fd_put(d);
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+
+ return offset;
+}
+RTM_EXPORT(lseek);
+
+#ifndef _WIN32 /* we can not implement these functions */
+/**
+ * this function is a POSIX compliant version, which will rename old file name
+ * to new file name.
+ *
+ * @param old the old file name.
+ * @param new the new file name.
+ *
+ * @return 0 on successful, -1 on failed.
+ *
+ * note: the old and new file name must be belong to a same file system.
+ */
+int rename(const char *old_file, const char *new_file)
+{
+ int result;
+
+ result = dfs_file_rename(old_file, new_file);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ return 0;
+}
+RTM_EXPORT(rename);
+#endif
+
+/**
+ * this function is a POSIX compliant version, which will unlink (remove) a
+ * specified path file from file system.
+ *
+ * @param pathname the specified path name to be unlinked.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int unlink(const char *pathname)
+{
+ int result;
+
+ result = dfs_file_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ return 0;
+}
+RTM_EXPORT(unlink);
+
+/**
+ * this function is a POSIX compliant version, which will get file information.
+ *
+ * @param file the file name
+ * @param buf the data buffer to save stat description.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int stat(const char *file, struct stat *buf)
+{
+ int result;
+
+ result = dfs_file_stat(file, buf);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ return result;
+}
+RTM_EXPORT(stat);
+
+/**
+ * this function is a POSIX compliant version, which will get file status.
+ *
+ * @param fildes the file description
+ * @param buf the data buffer to save stat description.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int fstat(int fildes, struct stat *buf)
+{
+ struct dfs_fd *d;
+
+ /* get the fd */
+ d = fd_get(fildes);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ /* it's the root directory */
+ buf->st_dev = 0;
+
+ buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
+ S_IWUSR | S_IWGRP | S_IWOTH;
+ if (d->type == FT_DIRECTORY)
+ {
+ buf->st_mode &= ~S_IFREG;
+ buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
+ }
+
+ buf->st_size = d->size;
+ buf->st_mtime = 0;
+
+ fd_put(d);
+
+ return RT_EOK;
+}
+RTM_EXPORT(fstat);
+
+/**
+ * this function is a POSIX compliant version, which shall request that all data
+ * for the open file descriptor named by fildes is to be transferred to the storage
+ * device associated with the file described by fildes.
+ *
+ * @param fildes the file description
+ *
+ * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
+ * set to indicate the error.
+ */
+int fsync(int fildes)
+{
+ int ret;
+ struct dfs_fd *d;
+
+ /* get the fd */
+ d = fd_get(fildes);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+ return -1;
+ }
+
+ ret = dfs_file_flush(d);
+
+ fd_put(d);
+ return ret;
+}
+RTM_EXPORT(fsync);
+
+/**
+ * this function is a POSIX compliant version, which shall perform a variety of
+ * control functions on devices.
+ *
+ * @param fildes the file description
+ * @param cmd the specified command
+ * @param data represents the additional information that is needed by this
+ * specific device to perform the requested function.
+ *
+ * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
+ * set to indicate the error.
+ */
+int fcntl(int fildes, int cmd, ...)
+{
+ int ret = -1;
+ struct dfs_fd *d;
+
+ /* get the fd */
+ d = fd_get(fildes);
+ if (d)
+ {
+ void *arg;
+ va_list ap;
+
+ va_start(ap, cmd);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ ret = dfs_file_ioctl(d, cmd, arg);
+ fd_put(d);
+ }
+ else ret = -EBADF;
+
+ if (ret < 0)
+ {
+ rt_set_errno(ret);
+ ret = -1;
+ }
+
+ return ret;
+}
+RTM_EXPORT(fcntl);
+
+/**
+ * this function is a POSIX compliant version, which shall perform a variety of
+ * control functions on devices.
+ *
+ * @param fildes the file description
+ * @param cmd the specified command
+ * @param data represents the additional information that is needed by this
+ * specific device to perform the requested function.
+ *
+ * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
+ * set to indicate the error.
+ */
+int ioctl(int fildes, int cmd, ...)
+{
+ void *arg;
+ va_list ap;
+
+ va_start(ap, cmd);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ /* we use fcntl for this API. */
+ return fcntl(fildes, cmd, arg);
+}
+RTM_EXPORT(ioctl);
+
+/**
+ *
+ * this function is a POSIX compliant version, which cause the regular file
+ * referenced by fd to be truncated to a size of precisely length bytes.
+ * @param fd the file descriptor.
+ * @param length the length to be truncated.
+ *
+ * @return Upon successful completion, ftruncate() shall return 0;
+ * otherwise, -1 shall be returned and errno set to indicate the error.
+ */
+int ftruncate(int fd, off_t length)
+{
+ int result;
+ struct dfs_fd *d;
+
+ d = fd_get(fd);
+ if (d == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ if (length < 0)
+ {
+ fd_put(d);
+ rt_set_errno(-EINVAL);
+
+ return -1;
+ }
+ result = dfs_file_ftruncate(d, length);
+ if (result < 0)
+ {
+ fd_put(d);
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ /* release the ref-count of fd */
+ fd_put(d);
+
+ return 0;
+}
+RTM_EXPORT(ftruncate);
+
+/**
+ * this function is a POSIX compliant version, which will return the
+ * information about a mounted file system.
+ *
+ * @param path the path which mounted file system.
+ * @param buf the buffer to save the returned information.
+ *
+ * @return 0 on successful, others on failed.
+ */
+int statfs(const char *path, struct statfs *buf)
+{
+ int result;
+
+ result = dfs_statfs(path, buf);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ return result;
+}
+RTM_EXPORT(statfs);
+
+/**
+ * this function is a POSIX compliant version, which will make a directory
+ *
+ * @param path the directory path to be made.
+ * @param mode
+ *
+ * @return 0 on successful, others on failed.
+ */
+int mkdir(const char *path, mode_t mode)
+{
+ int fd;
+ struct dfs_fd *d;
+ int result;
+
+ fd = fd_new();
+ if (fd == -1)
+ {
+ rt_set_errno(-ENOMEM);
+
+ return -1;
+ }
+
+ d = fd_get(fd);
+
+ result = dfs_file_open(d, path, O_DIRECTORY | O_CREAT);
+
+ if (result < 0)
+ {
+ fd_put(d);
+ fd_put(d);
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ dfs_file_close(d);
+ fd_put(d);
+ fd_put(d);
+
+ return 0;
+}
+RTM_EXPORT(mkdir);
+
+/**
+ * this function is a POSIX compliant version, which will remove a directory.
+ *
+ * @param pathname the path name to be removed.
+ *
+ * @return 0 on successful, others on failed.
+ */
+int rmdir(const char *pathname)
+{
+ int result;
+
+ result = dfs_file_unlink(pathname);
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+
+ return 0;
+}
+RTM_EXPORT(rmdir);
+
+/**
+ * this function is a POSIX compliant version, which will open a directory.
+ *
+ * @param name the path name to be open.
+ *
+ * @return the DIR pointer of directory, NULL on open directory failed.
+ */
+DIR *opendir(const char *name)
+{
+ struct dfs_fd *d;
+ int fd, result;
+ DIR *t;
+
+ t = NULL;
+
+ /* allocate a fd */
+ fd = fd_new();
+ if (fd == -1)
+ {
+ rt_set_errno(-ENOMEM);
+
+ return NULL;
+ }
+ d = fd_get(fd);
+
+ result = dfs_file_open(d, name, O_RDONLY | O_DIRECTORY);
+ if (result >= 0)
+ {
+ /* open successfully */
+ t = (DIR *) rt_malloc(sizeof(DIR));
+ if (t == NULL)
+ {
+ dfs_file_close(d);
+ fd_put(d);
+ }
+ else
+ {
+ memset(t, 0, sizeof(DIR));
+
+ t->fd = fd;
+ }
+ fd_put(d);
+
+ return t;
+ }
+
+ /* open failed */
+ fd_put(d);
+ fd_put(d);
+ rt_set_errno(result);
+
+ return NULL;
+}
+RTM_EXPORT(opendir);
+
+/**
+ * this function is a POSIX compliant version, which will return a pointer
+ * to a dirent structure representing the next directory entry in the
+ * directory stream.
+ *
+ * @param d the directory stream pointer.
+ *
+ * @return the next directory entry, NULL on the end of directory or failed.
+ */
+struct dirent *readdir(DIR *d)
+{
+ int result;
+ struct dfs_fd *fd;
+
+ fd = fd_get(d->fd);
+ if (fd == NULL)
+ {
+ rt_set_errno(-EBADF);
+ return NULL;
+ }
+
+ if (d->num)
+ {
+ struct dirent *dirent_ptr;
+ dirent_ptr = (struct dirent *)&d->buf[d->cur];
+ d->cur += dirent_ptr->d_reclen;
+ }
+
+ if (!d->num || d->cur >= d->num)
+ {
+ /* get a new entry */
+ result = dfs_file_getdents(fd,
+ (struct dirent *)d->buf,
+ sizeof(d->buf) - 1);
+ if (result <= 0)
+ {
+ fd_put(fd);
+ rt_set_errno(result);
+
+ return NULL;
+ }
+
+ d->num = result;
+ d->cur = 0; /* current entry index */
+ }
+
+ fd_put(fd);
+
+ return (struct dirent *)(d->buf + d->cur);
+}
+RTM_EXPORT(readdir);
+
+/**
+ * this function is a POSIX compliant version, which will return current
+ * location in directory stream.
+ *
+ * @param d the directory stream pointer.
+ *
+ * @return the current location in directory stream.
+ */
+long telldir(DIR *d)
+{
+ struct dfs_fd *fd;
+ long result;
+
+ fd = fd_get(d->fd);
+ if (fd == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return 0;
+ }
+
+ result = fd->pos - d->num + d->cur;
+ fd_put(fd);
+
+ return result;
+}
+RTM_EXPORT(telldir);
+
+/**
+ * this function is a POSIX compliant version, which will set position of
+ * next directory structure in the directory stream.
+ *
+ * @param d the directory stream.
+ * @param offset the offset in directory stream.
+ */
+void seekdir(DIR *d, off_t offset)
+{
+ struct dfs_fd *fd;
+
+ fd = fd_get(d->fd);
+ if (fd == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return ;
+ }
+
+ /* seek to the offset position of directory */
+ if (dfs_file_lseek(fd, offset) >= 0)
+ d->num = d->cur = 0;
+ fd_put(fd);
+}
+RTM_EXPORT(seekdir);
+
+/**
+ * this function is a POSIX compliant version, which will reset directory
+ * stream.
+ *
+ * @param d the directory stream.
+ */
+void rewinddir(DIR *d)
+{
+ struct dfs_fd *fd;
+
+ fd = fd_get(d->fd);
+ if (fd == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return ;
+ }
+
+ /* seek to the beginning of directory */
+ if (dfs_file_lseek(fd, 0) >= 0)
+ d->num = d->cur = 0;
+ fd_put(fd);
+}
+RTM_EXPORT(rewinddir);
+
+/**
+ * this function is a POSIX compliant version, which will close a directory
+ * stream.
+ *
+ * @param d the directory stream.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int closedir(DIR *d)
+{
+ int result;
+ struct dfs_fd *fd;
+
+ fd = fd_get(d->fd);
+ if (fd == NULL)
+ {
+ rt_set_errno(-EBADF);
+
+ return -1;
+ }
+
+ result = dfs_file_close(fd);
+ fd_put(fd);
+
+ fd_put(fd);
+ rt_free(d);
+
+ if (result < 0)
+ {
+ rt_set_errno(result);
+
+ return -1;
+ }
+ else
+ return 0;
+}
+RTM_EXPORT(closedir);
+
+#ifdef DFS_USING_WORKDIR
+/**
+ * this function is a POSIX compliant version, which will change working
+ * directory.
+ *
+ * @param path the path name to be changed to.
+ *
+ * @return 0 on successful, -1 on failed.
+ */
+int chdir(const char *path)
+{
+ char *fullpath;
+ DIR *d;
+
+ if (path == NULL)
+ {
+ dfs_lock();
+ rt_kprintf("%s\n", working_directory);
+ dfs_unlock();
+
+ return 0;
+ }
+
+ if (strlen(path) > DFS_PATH_MAX)
+ {
+ rt_set_errno(-ENOTDIR);
+
+ return -1;
+ }
+
+ fullpath = dfs_normalize_path(NULL, path);
+ if (fullpath == NULL)
+ {
+ rt_set_errno(-ENOTDIR);
+
+ return -1; /* build path failed */
+ }
+
+ dfs_lock();
+ d = opendir(fullpath);
+ if (d == NULL)
+ {
+ rt_free(fullpath);
+ /* this is a not exist directory */
+ dfs_unlock();
+
+ return -1;
+ }
+
+ /* close directory stream */
+ closedir(d);
+
+ /* copy full path to working directory */
+ strncpy(working_directory, fullpath, DFS_PATH_MAX);
+ /* release normalize directory path name */
+ rt_free(fullpath);
+
+ dfs_unlock();
+
+ return 0;
+}
+RTM_EXPORT(chdir);
+
+#ifdef RT_USING_FINSH
+FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory);
+#endif
+#endif
+
+/**
+ * this function is a POSIX compliant version, which shall check the file named
+ * by the pathname pointed to by the path argument for accessibility according
+ * to the bit pattern contained in amode.
+ *
+ * @param path the specified file/dir path.
+ * @param amode the value is either the bitwise-inclusive OR of the access
+ * permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
+ */
+int access(const char *path, int amode)
+{
+ struct stat sb;
+ if (stat(path, &sb) < 0)
+ return -1; /* already sets errno */
+
+ /* ignore R_OK,W_OK,X_OK condition */
+ return 0;
+}
+
+/**
+ * this function is a POSIX compliant version, which will return current
+ * working directory.
+ *
+ * @param buf the returned current directory.
+ * @param size the buffer size.
+ *
+ * @return the returned current directory.
+ */
+char *getcwd(char *buf, size_t size)
+{
+#ifdef DFS_USING_WORKDIR
+ dfs_lock();
+ strncpy(buf, working_directory, size);
+ dfs_unlock();
+#else
+ rt_kprintf(NO_WORKING_DIR);
+#endif
+
+ return buf;
+}
+RTM_EXPORT(getcwd);
+
+#ifdef RT_USING_POSIX_TERMIOS
+#include "termios.h"
+int isatty(int fd)
+{
+ struct termios ts;
+ return(tcgetattr(fd, &ts) != -1); /*true if no error (is a tty)*/
+}
+#else
+int isatty(int fd)
+{
+ if (fd >=0 && fd < 3)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+#endif
+RTM_EXPORT(isatty);
+
+char *ttyname(int fd)
+{
+ return "/dev/tty"; /* TODO: need to add more specific */
+}
+RTM_EXPORT(ttyname);
+
+unsigned int sleep(unsigned int seconds)
+{
+ if (rt_thread_self() != RT_NULL)
+ {
+ ssleep(seconds);
+ }
+ else /* scheduler has not run yet */
+ {
+ while(seconds > 0)
+ {
+ udelay(1000000u);
+ seconds --;
+ }
+ }
+
+ return 0;
+}
+RTM_EXPORT(sleep);
+
+int usleep(useconds_t usec)
+{
+ if (rt_thread_self() != RT_NULL)
+ {
+ msleep(usec / 1000u);
+ }
+ else /* scheduler has not run yet */
+ {
+ udelay(usec / 1000u);
+ }
+ udelay(usec % 1000u);
+
+ return 0;
+}
+RTM_EXPORT(usleep);
+
+pid_t gettid(void)
+{
+ /*TODO*/
+ return 0;
+}
+
+pid_t getpid(void)
+{
+ return gettid();
+}
+RTM_EXPORT(getpid);
+
+pid_t getppid(void)
+{
+ return 0;
+}
+RTM_EXPORT(getppid);
+
+uid_t getuid(void)
+{
+ return 0; /*ROOT*/
+}
+RTM_EXPORT(getuid);
+
+uid_t geteuid(void)
+{
+ return 0; /*ROOT*/
+}
+RTM_EXPORT(geteuid);
+
+gid_t getgid(void)
+{
+ return 0; /*ROOT*/
+}
+RTM_EXPORT(getgid);
+
+gid_t getegid(void)
+{
+ return 0; /*ROOT*/
+}
+RTM_EXPORT(getegid);
diff --git a/components/libc/posix/termios/SConscript b/components/libc/posix/termios/SConscript
index 381eb5ad8b..bd9a528461 100644
--- a/components/libc/posix/termios/SConscript
+++ b/components/libc/posix/termios/SConscript
@@ -6,7 +6,7 @@ cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
-group = DefineGroup('libc', src,
+group = DefineGroup('POSIX', src,
depend = ['RT_USING_LIBC', 'RT_USING_POSIX', 'RT_USING_POSIX_TERMIOS'],
CPPPATH = CPPPATH)