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