1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2012-11-23 Yihui The first version
9*10465441SEvalZero * 2013-11-24 aozima fixed _sys_read()/_sys_write() issues.
10*10465441SEvalZero * 2014-08-03 bernard If using msh, use system() implementation
11*10465441SEvalZero * in msh.
12*10465441SEvalZero */
13*10465441SEvalZero
14*10465441SEvalZero #include <string.h>
15*10465441SEvalZero #include <rt_sys.h>
16*10465441SEvalZero
17*10465441SEvalZero #include "rtthread.h"
18*10465441SEvalZero #include "libc.h"
19*10465441SEvalZero
20*10465441SEvalZero #ifdef RT_USING_DFS
21*10465441SEvalZero #include "dfs_posix.h"
22*10465441SEvalZero #endif
23*10465441SEvalZero
24*10465441SEvalZero #ifdef __CLANG_ARM
25*10465441SEvalZero __asm(".global __use_no_semihosting\n\t");
26*10465441SEvalZero #else
27*10465441SEvalZero #pragma import(__use_no_semihosting_swi)
28*10465441SEvalZero #endif
29*10465441SEvalZero
30*10465441SEvalZero /* Standard IO device handles. */
31*10465441SEvalZero #define STDIN 0
32*10465441SEvalZero #define STDOUT 1
33*10465441SEvalZero #define STDERR 2
34*10465441SEvalZero
35*10465441SEvalZero /* Standard IO device name defines. */
36*10465441SEvalZero const char __stdin_name[] = "STDIN";
37*10465441SEvalZero const char __stdout_name[] = "STDOUT";
38*10465441SEvalZero const char __stderr_name[] = "STDERR";
39*10465441SEvalZero
40*10465441SEvalZero /**
41*10465441SEvalZero * required by fopen() and freopen().
42*10465441SEvalZero *
43*10465441SEvalZero * @param name - file name with path.
44*10465441SEvalZero * @param openmode - a bitmap hose bits mostly correspond directly to
45*10465441SEvalZero * the ISO mode specification.
46*10465441SEvalZero * @return -1 if an error occurs.
47*10465441SEvalZero */
_sys_open(const char * name,int openmode)48*10465441SEvalZero FILEHANDLE _sys_open(const char *name, int openmode)
49*10465441SEvalZero {
50*10465441SEvalZero #ifdef RT_USING_DFS
51*10465441SEvalZero int fd;
52*10465441SEvalZero int mode = O_RDONLY;
53*10465441SEvalZero #endif
54*10465441SEvalZero
55*10465441SEvalZero /* Register standard Input Output devices. */
56*10465441SEvalZero if (strcmp(name, __stdin_name) == 0)
57*10465441SEvalZero return (STDIN);
58*10465441SEvalZero if (strcmp(name, __stdout_name) == 0)
59*10465441SEvalZero return (STDOUT);
60*10465441SEvalZero if (strcmp(name, __stderr_name) == 0)
61*10465441SEvalZero return (STDERR);
62*10465441SEvalZero
63*10465441SEvalZero #ifndef RT_USING_DFS
64*10465441SEvalZero return -1;
65*10465441SEvalZero #else
66*10465441SEvalZero /* Correct openmode from fopen to open */
67*10465441SEvalZero if (openmode & OPEN_PLUS)
68*10465441SEvalZero {
69*10465441SEvalZero if (openmode & OPEN_W)
70*10465441SEvalZero {
71*10465441SEvalZero mode |= (O_RDWR | O_TRUNC | O_CREAT);
72*10465441SEvalZero }
73*10465441SEvalZero else if (openmode & OPEN_A)
74*10465441SEvalZero {
75*10465441SEvalZero mode |= (O_RDWR | O_APPEND | O_CREAT);
76*10465441SEvalZero }
77*10465441SEvalZero else
78*10465441SEvalZero mode |= O_RDWR;
79*10465441SEvalZero }
80*10465441SEvalZero else
81*10465441SEvalZero {
82*10465441SEvalZero if (openmode & OPEN_W)
83*10465441SEvalZero {
84*10465441SEvalZero mode |= (O_WRONLY | O_TRUNC | O_CREAT);
85*10465441SEvalZero }
86*10465441SEvalZero else if (openmode & OPEN_A)
87*10465441SEvalZero {
88*10465441SEvalZero mode |= (O_WRONLY | O_APPEND | O_CREAT);
89*10465441SEvalZero }
90*10465441SEvalZero }
91*10465441SEvalZero
92*10465441SEvalZero fd = open(name, mode, 0);
93*10465441SEvalZero if (fd < 0)
94*10465441SEvalZero return -1;
95*10465441SEvalZero else
96*10465441SEvalZero return fd;
97*10465441SEvalZero #endif
98*10465441SEvalZero }
99*10465441SEvalZero
_sys_close(FILEHANDLE fh)100*10465441SEvalZero int _sys_close(FILEHANDLE fh)
101*10465441SEvalZero {
102*10465441SEvalZero #ifndef RT_USING_DFS
103*10465441SEvalZero return 0;
104*10465441SEvalZero #else
105*10465441SEvalZero if (fh <= STDERR) return 0;
106*10465441SEvalZero
107*10465441SEvalZero return close(fh);
108*10465441SEvalZero #endif
109*10465441SEvalZero }
110*10465441SEvalZero
111*10465441SEvalZero /*
112*10465441SEvalZero * Read from a file. Can return:
113*10465441SEvalZero * - zero if the read was completely successful
114*10465441SEvalZero * - the number of bytes _not_ read, if the read was partially successful
115*10465441SEvalZero * - the number of bytes not read, plus the top bit set (0x80000000), if
116*10465441SEvalZero * the read was partially successful due to end of file
117*10465441SEvalZero * - -1 if some error other than EOF occurred
118*10465441SEvalZero *
119*10465441SEvalZero * It is also legal to signal EOF by returning no data but
120*10465441SEvalZero * signalling no error (i.e. the top-bit-set mechanism need never
121*10465441SEvalZero * be used).
122*10465441SEvalZero *
123*10465441SEvalZero * So if (for example) the user is trying to read 8 bytes at a time
124*10465441SEvalZero * from a file in which only 5 remain, this routine can do three
125*10465441SEvalZero * equally valid things:
126*10465441SEvalZero *
127*10465441SEvalZero * - it can return 0x80000003 (3 bytes not read due to EOF)
128*10465441SEvalZero * - OR it can return 3 (3 bytes not read), and then return
129*10465441SEvalZero * 0x80000008 (8 bytes not read due to EOF) on the next attempt
130*10465441SEvalZero * - OR it can return 3 (3 bytes not read), and then return
131*10465441SEvalZero * 8 (8 bytes not read, meaning 0 read, meaning EOF) on the next
132*10465441SEvalZero * attempt
133*10465441SEvalZero *
134*10465441SEvalZero * `mode' exists for historical reasons and must be ignored.
135*10465441SEvalZero */
_sys_read(FILEHANDLE fh,unsigned char * buf,unsigned len,int mode)136*10465441SEvalZero int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode)
137*10465441SEvalZero {
138*10465441SEvalZero #ifdef RT_USING_DFS
139*10465441SEvalZero int size;
140*10465441SEvalZero #endif
141*10465441SEvalZero
142*10465441SEvalZero if (fh == STDIN)
143*10465441SEvalZero {
144*10465441SEvalZero #ifdef RT_USING_POSIX
145*10465441SEvalZero size = libc_stdio_read(buf, len);
146*10465441SEvalZero return len - size;
147*10465441SEvalZero #else
148*10465441SEvalZero /* no stdin */
149*10465441SEvalZero return -1;
150*10465441SEvalZero #endif
151*10465441SEvalZero }
152*10465441SEvalZero
153*10465441SEvalZero if ((fh == STDOUT) || (fh == STDERR))
154*10465441SEvalZero return -1;
155*10465441SEvalZero
156*10465441SEvalZero #ifndef RT_USING_DFS
157*10465441SEvalZero return 0;
158*10465441SEvalZero #else
159*10465441SEvalZero size = read(fh, buf, len);
160*10465441SEvalZero if (size >= 0)
161*10465441SEvalZero return len - size;
162*10465441SEvalZero else
163*10465441SEvalZero return -1;
164*10465441SEvalZero #endif
165*10465441SEvalZero }
166*10465441SEvalZero
167*10465441SEvalZero /*
168*10465441SEvalZero * Write to a file. Returns 0 on success, negative on error, and
169*10465441SEvalZero * the number of characters _not_ written on partial success.
170*10465441SEvalZero * `mode' exists for historical reasons and must be ignored.
171*10465441SEvalZero */
_sys_write(FILEHANDLE fh,const unsigned char * buf,unsigned len,int mode)172*10465441SEvalZero int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
173*10465441SEvalZero {
174*10465441SEvalZero #ifdef RT_USING_DFS
175*10465441SEvalZero int size;
176*10465441SEvalZero #endif
177*10465441SEvalZero
178*10465441SEvalZero if ((fh == STDOUT) || (fh == STDERR))
179*10465441SEvalZero {
180*10465441SEvalZero #if !defined(RT_USING_CONSOLE) || !defined(RT_USING_DEVICE)
181*10465441SEvalZero return 0;
182*10465441SEvalZero #else
183*10465441SEvalZero #ifdef RT_USING_POSIX
184*10465441SEvalZero size = libc_stdio_write(buf, len);
185*10465441SEvalZero return len - size;
186*10465441SEvalZero #else
187*10465441SEvalZero if (rt_console_get_device())
188*10465441SEvalZero {
189*10465441SEvalZero rt_device_write(rt_console_get_device(), -1, buf, len);
190*10465441SEvalZero return 0;
191*10465441SEvalZero }
192*10465441SEvalZero
193*10465441SEvalZero return -1;
194*10465441SEvalZero #endif
195*10465441SEvalZero #endif
196*10465441SEvalZero }
197*10465441SEvalZero
198*10465441SEvalZero if (fh == STDIN) return -1;
199*10465441SEvalZero
200*10465441SEvalZero #ifndef RT_USING_DFS
201*10465441SEvalZero return 0;
202*10465441SEvalZero #else
203*10465441SEvalZero size = write(fh, buf, len);
204*10465441SEvalZero if (size >= 0)
205*10465441SEvalZero return len - size;
206*10465441SEvalZero else
207*10465441SEvalZero return -1;
208*10465441SEvalZero #endif
209*10465441SEvalZero }
210*10465441SEvalZero
211*10465441SEvalZero /*
212*10465441SEvalZero * Move the file position to a given offset from the file start.
213*10465441SEvalZero * Returns >=0 on success, <0 on failure.
214*10465441SEvalZero */
_sys_seek(FILEHANDLE fh,long pos)215*10465441SEvalZero int _sys_seek(FILEHANDLE fh, long pos)
216*10465441SEvalZero {
217*10465441SEvalZero if (fh < STDERR)
218*10465441SEvalZero return -1;
219*10465441SEvalZero
220*10465441SEvalZero #ifndef RT_USING_DFS
221*10465441SEvalZero return -1;
222*10465441SEvalZero #else
223*10465441SEvalZero
224*10465441SEvalZero /* position is relative to the start of file fh */
225*10465441SEvalZero return lseek(fh, pos, 0);
226*10465441SEvalZero #endif
227*10465441SEvalZero }
228*10465441SEvalZero
229*10465441SEvalZero /**
230*10465441SEvalZero * used by tmpnam() or tmpfile()
231*10465441SEvalZero */
_sys_tmpnam(char * name,int fileno,unsigned maxlength)232*10465441SEvalZero int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
233*10465441SEvalZero {
234*10465441SEvalZero return -1;
235*10465441SEvalZero }
236*10465441SEvalZero
_sys_command_string(char * cmd,int len)237*10465441SEvalZero char *_sys_command_string(char *cmd, int len)
238*10465441SEvalZero {
239*10465441SEvalZero /* no support */
240*10465441SEvalZero return RT_NULL;
241*10465441SEvalZero }
242*10465441SEvalZero
243*10465441SEvalZero /* This function writes a character to the console. */
_ttywrch(int ch)244*10465441SEvalZero void _ttywrch(int ch)
245*10465441SEvalZero {
246*10465441SEvalZero #ifdef RT_USING_CONSOLE
247*10465441SEvalZero char c;
248*10465441SEvalZero
249*10465441SEvalZero c = (char)ch;
250*10465441SEvalZero rt_kprintf(&c);
251*10465441SEvalZero #endif
252*10465441SEvalZero }
253*10465441SEvalZero
_sys_exit(int return_code)254*10465441SEvalZero void _sys_exit(int return_code)
255*10465441SEvalZero {
256*10465441SEvalZero /* TODO: perhaps exit the thread which is invoking this function */
257*10465441SEvalZero while (1);
258*10465441SEvalZero }
259*10465441SEvalZero
260*10465441SEvalZero /**
261*10465441SEvalZero * return current length of file.
262*10465441SEvalZero *
263*10465441SEvalZero * @param fh - file handle
264*10465441SEvalZero * @return file length, or -1 on failed
265*10465441SEvalZero */
_sys_flen(FILEHANDLE fh)266*10465441SEvalZero long _sys_flen(FILEHANDLE fh)
267*10465441SEvalZero {
268*10465441SEvalZero struct stat stat;
269*10465441SEvalZero
270*10465441SEvalZero if (fh < STDERR)
271*10465441SEvalZero return -1;
272*10465441SEvalZero
273*10465441SEvalZero #ifndef RT_USING_DFS
274*10465441SEvalZero return -1;
275*10465441SEvalZero #else
276*10465441SEvalZero fstat(fh, &stat);
277*10465441SEvalZero return stat.st_size;
278*10465441SEvalZero #endif
279*10465441SEvalZero }
280*10465441SEvalZero
_sys_istty(FILEHANDLE fh)281*10465441SEvalZero int _sys_istty(FILEHANDLE fh)
282*10465441SEvalZero {
283*10465441SEvalZero if((STDIN <= fh) && (fh <= STDERR))
284*10465441SEvalZero return 1;
285*10465441SEvalZero else
286*10465441SEvalZero return 0;
287*10465441SEvalZero }
288*10465441SEvalZero
remove(const char * filename)289*10465441SEvalZero int remove(const char *filename)
290*10465441SEvalZero {
291*10465441SEvalZero #ifndef RT_USING_DFS
292*10465441SEvalZero return -1;
293*10465441SEvalZero #else
294*10465441SEvalZero return unlink(filename);
295*10465441SEvalZero #endif
296*10465441SEvalZero }
297*10465441SEvalZero
298*10465441SEvalZero #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) && defined(RT_USING_MODULE) && defined(RT_USING_DFS)
299*10465441SEvalZero /* use system(const char *string) implementation in the msh */
300*10465441SEvalZero #else
system(const char * string)301*10465441SEvalZero int system(const char *string)
302*10465441SEvalZero {
303*10465441SEvalZero RT_ASSERT(0);
304*10465441SEvalZero for (;;);
305*10465441SEvalZero }
306*10465441SEvalZero #endif
307*10465441SEvalZero
308*10465441SEvalZero #ifdef __MICROLIB
309*10465441SEvalZero #include <stdio.h>
310*10465441SEvalZero
fputc(int c,FILE * f)311*10465441SEvalZero int fputc(int c, FILE *f)
312*10465441SEvalZero {
313*10465441SEvalZero char ch[2] = {0};
314*10465441SEvalZero
315*10465441SEvalZero ch[0] = c;
316*10465441SEvalZero rt_kprintf(&ch[0]);
317*10465441SEvalZero return 1;
318*10465441SEvalZero }
319*10465441SEvalZero
fgetc(FILE * f)320*10465441SEvalZero int fgetc(FILE *f)
321*10465441SEvalZero {
322*10465441SEvalZero #ifdef RT_USING_POSIX
323*10465441SEvalZero char ch;
324*10465441SEvalZero
325*10465441SEvalZero if (libc_stdio_read(&ch, 1) == 1)
326*10465441SEvalZero return ch;
327*10465441SEvalZero #endif
328*10465441SEvalZero
329*10465441SEvalZero return -1;
330*10465441SEvalZero }
331*10465441SEvalZero #endif
332