1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-02-11     Meco Man     remove _gettimeofday_r() and _times_r()
9  * 2021-02-13     Meco Man     re-implement exit() and abort()
10  * 2021-02-21     Meco Man     improve and beautify syscalls
11  * 2021-02-24     Meco Man     fix bug of _isatty_r()
12  */
13 
14 #include <reent.h>
15 #include <rtthread.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stddef.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <sys/errno.h>
22 #include <sys/stat.h>
23 #ifdef RT_USING_POSIX_STDIO
24 #include <posix/stdio.h>
25 #endif /* RT_USING_POSIX_STDIO */
26 #include <posix/stdlib.h>
27 #ifdef RT_USING_MODULE
28 #include <dlmodule.h>
29 #endif /* RT_USING_MODULE */
30 #include <compiler_private.h>
31 #define DBG_TAG    "newlib.syscalls"
32 #define DBG_LVL    DBG_INFO
33 #include <rtdbg.h>
34 
35 #ifdef RT_USING_HEAP /* Memory routine */
_malloc_r(struct _reent * ptr,size_t size)36 void *_malloc_r(struct _reent *ptr, size_t size)
37 {
38     void* result;
39 
40     result = (void*)rt_malloc(size);
41     if (result == RT_NULL)
42     {
43         ptr->_errno = ENOMEM;
44     }
45 
46     return result;
47 }
48 
_realloc_r(struct _reent * ptr,void * old,size_t newlen)49 void *_realloc_r(struct _reent *ptr, void *old, size_t newlen)
50 {
51     void* result;
52 
53     result = (void*)rt_realloc(old, newlen);
54     if (result == RT_NULL)
55     {
56         ptr->_errno = ENOMEM;
57     }
58 
59     return result;
60 }
61 
_calloc_r(struct _reent * ptr,size_t size,size_t len)62 void *_calloc_r(struct _reent *ptr, size_t size, size_t len)
63 {
64     void* result;
65 
66     result = (void*)rt_calloc(size, len);
67     if (result == RT_NULL)
68     {
69         ptr->_errno = ENOMEM;
70     }
71 
72     return result;
73 }
74 
_free_r(struct _reent * ptr,void * addr)75 void _free_r(struct _reent *ptr, void *addr)
76 {
77     rt_free(addr);
78 }
79 
80 #else
_sbrk_r(struct _reent * ptr,ptrdiff_t incr)81 void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
82 {
83     LOG_E("Please enable RT_USING_HEAP");
84     RT_ASSERT(0);
85     return RT_NULL;
86 }
87 #endif /*RT_USING_HEAP*/
88 
__libc_init_array(void)89 void __libc_init_array(void)
90 {
91     /* we not use __libc init_aray to initialize C++ objects */
92     /* __libc_init_array is ARM code, not Thumb; it will cause a hardfault. */
93 }
94 
95 /* Reentrant versions of system calls.  */
96 #ifndef _REENT_ONLY
__errno(void)97 int *__errno(void)
98 {
99   return _rt_errno();
100 }
101 #endif
102 
_getpid_r(struct _reent * ptr)103 int _getpid_r(struct _reent *ptr)
104 {
105     return 0;
106 }
107 
_close_r(struct _reent * ptr,int fd)108 int _close_r(struct _reent *ptr, int fd)
109 {
110 #ifdef DFS_USING_POSIX
111     return close(fd);
112 #else
113     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
114     ptr->_errno = ENOTSUP;
115     return -1;
116 #endif /* DFS_USING_POSIX */
117 }
118 
_execve_r(struct _reent * ptr,const char * name,char * const * argv,char * const * env)119 int _execve_r(struct _reent *ptr, const char * name, char *const *argv, char *const *env)
120 {
121     ptr->_errno = ENOTSUP;
122     return -1;
123 }
124 
_fcntl_r(struct _reent * ptr,int fd,int cmd,int arg)125 int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg)
126 {
127     ptr->_errno = ENOTSUP;
128     return -1;
129 }
130 
_fork_r(struct _reent * ptr)131 int _fork_r(struct _reent *ptr)
132 {
133     ptr->_errno = ENOTSUP;
134     return -1;
135 }
136 
_fstat_r(struct _reent * ptr,int fd,struct stat * pstat)137 int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat)
138 {
139     ptr->_errno = ENOTSUP;
140     return -1;
141 }
142 
_isatty_r(struct _reent * ptr,int fd)143 int _isatty_r(struct _reent *ptr, int fd)
144 {
145     if (fd >=0 && fd < 3)
146     {
147         return 1;
148     }
149     else
150     {
151         return 0;
152     }
153 }
154 
_kill_r(struct _reent * ptr,int pid,int sig)155 int _kill_r(struct _reent *ptr, int pid, int sig)
156 {
157     ptr->_errno = ENOTSUP;
158     return -1;
159 }
160 
_link_r(struct _reent * ptr,const char * old,const char * new)161 int _link_r(struct _reent *ptr, const char *old, const char *new)
162 {
163     ptr->_errno = ENOTSUP;
164     return -1;
165 }
166 
_wait_r(struct _reent * ptr,int * status)167 int _wait_r(struct _reent *ptr, int *status)
168 {
169     ptr->_errno = ENOTSUP;
170     return -1;
171 }
172 
umask(mode_t mask)173 mode_t umask(mode_t mask)
174 {
175     return 022;
176 }
177 
flock(int fd,int operation)178 int flock(int fd, int operation)
179 {
180     return 0;
181 }
182 
_lseek_r(struct _reent * ptr,int fd,_off_t pos,int whence)183 _off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence)
184 {
185 #ifdef DFS_USING_POSIX
186     _off_t rc;
187     rc = lseek(fd, pos, whence);
188     return rc;
189 #else
190     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
191     ptr->_errno = ENOTSUP;
192     return -1;
193 #endif /* DFS_USING_POSIX */
194 }
195 
_mkdir_r(struct _reent * ptr,const char * name,int mode)196 int _mkdir_r(struct _reent *ptr, const char *name, int mode)
197 {
198 #ifdef DFS_USING_POSIX
199     int rc;
200     rc = mkdir(name, mode);
201     return rc;
202 #else
203     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
204     ptr->_errno = ENOTSUP;
205     return -1;
206 #endif /* DFS_USING_POSIX */
207 }
208 
_open_r(struct _reent * ptr,const char * file,int flags,int mode)209 int _open_r(struct _reent *ptr, const char *file, int flags, int mode)
210 {
211 #ifdef DFS_USING_POSIX
212     int rc;
213     rc = open(file, flags, mode);
214     return rc;
215 #else
216     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
217     ptr->_errno = ENOTSUP;
218     return -1;
219 #endif /* DFS_USING_POSIX */
220 }
221 
_read_r(struct _reent * ptr,int fd,void * buf,size_t nbytes)222 _ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes)
223 {
224 #ifdef DFS_USING_POSIX
225     _ssize_t rc;
226     if (fd == STDIN_FILENO)
227     {
228 #ifdef RT_USING_POSIX_STDIO
229         if (rt_posix_stdio_get_console() < 0)
230         {
231             LOG_W("Do not invoke standard input before initializing Compiler");
232             return 0;
233         }
234 #else
235         LOG_W("%s: %s", __func__, _WARNING_WITHOUT_STDIO);
236         ptr->_errno = ENOTSUP;
237         return -1;
238 #endif /* RT_USING_POSIX_STDIO */
239     }
240     else if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
241     {
242         ptr->_errno = ENOTSUP;
243         return -1;
244     }
245 
246     rc = read(fd, buf, nbytes);
247     return rc;
248 #else
249     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
250     ptr->_errno = ENOTSUP;
251     return -1;
252 #endif /* DFS_USING_POSIX */
253 }
254 
_rename_r(struct _reent * ptr,const char * old,const char * new)255 int _rename_r(struct _reent *ptr, const char *old, const char *new)
256 {
257 #ifdef DFS_USING_POSIX
258     int rc;
259     rc = rename(old, new);
260     return rc;
261 #else
262     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
263     ptr->_errno = ENOTSUP;
264     return -1;
265 #endif /* DFS_USING_POSIX */
266 }
267 
_stat_r(struct _reent * ptr,const char * file,struct stat * pstat)268 int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat)
269 {
270 #ifdef DFS_USING_POSIX
271     int rc;
272     rc = stat(file, pstat);
273     return rc;
274 #else
275     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
276     ptr->_errno = ENOTSUP;
277     return -1;
278 #endif /* DFS_USING_POSIX */
279 }
280 
_unlink_r(struct _reent * ptr,const char * file)281 int _unlink_r(struct _reent *ptr, const char *file)
282 {
283 #ifdef DFS_USING_POSIX
284     return unlink(file);
285 #else
286     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
287     ptr->_errno = ENOTSUP;
288     return -1;
289 #endif /* DFS_USING_POSIX */
290 }
291 
_write_r(struct _reent * ptr,int fd,const void * buf,size_t nbytes)292 _ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes)
293 {
294 #ifdef DFS_USING_POSIX
295     _ssize_t rc;
296 #endif /* DFS_USING_POSIX */
297 
298     if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
299     {
300 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
301         rt_device_t console;
302 
303         console = rt_console_get_device();
304         if (console)
305             return rt_device_write(console, -1, buf, nbytes);
306 #else
307         ptr->_errno = ENOTSUP;
308         return -1;
309 #endif /* defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) */
310     }
311     else if (fd == STDIN_FILENO)
312     {
313         ptr->_errno = ENOTSUP;
314         return -1;
315     }
316 
317 #ifdef DFS_USING_POSIX
318     rc = write(fd, buf, nbytes);
319     return rc;
320 #else
321     LOG_W("%s: %s", __func__, _WARNING_WITHOUT_FS);
322     ptr->_errno = ENOTSUP;
323     return -1;
324 #endif /* DFS_USING_POSIX */
325 }
326 
327 /* for exit() and abort() */
_exit(int status)328 __attribute__ ((noreturn)) void _exit (int status)
329 {
330     __rt_libc_exit(status);
331     while(1);
332 }
333 
334 /*
335 These functions are implemented and replaced by the 'common/time.c' file
336 int _gettimeofday_r(struct _reent *ptr, struct timeval *__tp, void *__tzp);
337 _CLOCK_T_  _times_r(struct _reent *ptr, struct tms *ptms);
338 */
339