source: asp3_tinet_ecnl_arm/trunk/ntshell/src/io_stub.c@ 374

Last change on this file since 374 was 374, checked in by coas-nagasima, 5 years ago

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.2 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2017 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37#include "shellif.h"
38#include <stdint.h>
39#include "ff.h"
40#include <kernel.h>
41#include <t_syslog.h>
42#include <t_stdlib.h>
43#include <sil.h>
44#include <string.h>
45#include "syssvc/serial.h"
46#include "syssvc/syslog.h"
47#include "socket_stub.h"
48#include "util/ntstdio.h"
49#include "usrcmd.h"
50#include "core/ntlibc.h"
51#include "kernel_cfg.h"
52#include "target_syssvc.h"
53
54int fresult2errno(FRESULT res)
55{
56 switch (res) {
57 case FR_INVALID_OBJECT:
58 return -EINVAL;
59 case FR_TOO_MANY_OPEN_FILES:
60 return -ENOMEM;
61 case FR_NO_FILE:
62 case FR_NO_PATH:
63 case FR_INVALID_DRIVE:
64 case FR_INVALID_NAME:
65 return -ENOENT;
66 case FR_DISK_ERR:
67 case FR_NO_FILESYSTEM:
68 case FR_NOT_ENABLED:
69 return -ENODEV;
70 case FR_WRITE_PROTECTED:
71 case FR_DENIED:
72 return -EACCES;
73 case FR_EXIST:
74 return -EEXIST;
75 case FR_INT_ERR:
76 default:
77 return -EIO;
78 }
79}
80
81static int file_close(struct SHELL_FILE *fp);
82static size_t file_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
83static size_t file_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
84static off_t file_seek(struct SHELL_FILE *fp, off_t ofs, int org);
85static int file_ioctl(struct SHELL_FILE *fp, int req, void *arg);
86static bool_t file_readable(struct SHELL_FILE *fp);
87static void file_delete(struct SHELL_FILE *fp);
88
89static int dir_close(struct SHELL_FILE *fp);
90static size_t dir_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
91static size_t dir_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
92static off_t dir_seek(struct SHELL_FILE *fp, off_t ofs, int org);
93static int dir_ioctl(struct SHELL_FILE *fp, int req, void *arg);
94static bool_t dir_readable(struct SHELL_FILE *fp);
95static void dir_delete(struct SHELL_FILE *fp);
96
97IO_TYPE IO_TYPE_FILE = { file_close, file_read, file_write, file_seek, file_ioctl, file_readable, file_delete };
98IO_TYPE IO_TYPE_DIR = { dir_close, dir_read, dir_write, dir_seek, dir_ioctl, dir_readable, dir_delete };
99
100int shell_open(const char *path, int flags, void *arg)
101{
102 FRESULT res;
103 struct SHELL_FILE *fp;
104
105 if (flags & O_DIRECTORY) {
106 fp = new_fp(&IO_TYPE_DIR, 0, 0);
107 if (fp == NULL)
108 return -ENOMEM;
109
110 fp->exinf = malloc(sizeof(struct SHELL_DIR));
111 memset(fp->exinf, 0, sizeof(struct SHELL_DIR));
112
113 FATFS_DIR *dir = &((struct SHELL_DIR *)fp->exinf)->dir;
114 FRESULT res;
115 if ((res = f_opendir(dir, path)) != FR_OK) {
116 return fresult2errno(res);
117 }
118 return 0;
119 }
120
121 fp = new_fp(&IO_TYPE_FILE, 0, 1);
122 if (fp == NULL)
123 return -ENOMEM;
124
125 fp->exinf = malloc(sizeof(FIL));
126 memset(fp->exinf, 0, sizeof(FIL));
127
128 BYTE fmd = 0;
129 switch (flags & O_ACCMODE) {
130 case O_RDONLY:
131 fmd = FA_READ;
132 break;
133 case O_WRONLY:
134 fmd = FA_WRITE;
135 break;
136 default:
137 fmd = FA_READ | FA_WRITE;
138 break;
139 }
140 /* ファイルを作成 */
141 if (flags & O_CREAT) {
142 /* 既存の内容は消す */
143 if (flags & O_TRUNC) {
144 fmd |= FA_CREATE_ALWAYS;
145 }
146 /* 新規作成の保障 */
147 else if (flags & O_EXCL) {
148 fmd |= FA_CREATE_NEW;
149 }
150 else {
151 fmd |= FA_OPEN_ALWAYS;
152 }
153 }
154 /* ある場合は開く */
155 else {
156 /* 既存の内容は消す */
157 if (flags & O_TRUNC) {
158 fmd |= FA_CREATE_ALWAYS;
159 }
160 }
161
162 if ((res = f_open((FIL *)fp->exinf, path, fmd)) == FR_OK) {
163 fp->handle = fp->fd;
164 return fp->fd;
165 }
166
167 return fresult2errno(res);
168}
169
170int file_close(struct SHELL_FILE *fp)
171{
172 FRESULT res;
173
174 if ((res = f_close((FIL *)fp->exinf)) == FR_OK) {
175 return 0;
176 }
177
178 return -EINVAL;
179}
180
181size_t file_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
182{
183 unsigned int ret = 0;
184 FRESULT res;
185
186 if ((res = f_read((FIL *)fp->exinf, data, len, &ret)) != FR_OK)
187 return -EIO;
188
189 return ret;
190}
191
192size_t file_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
193{
194 unsigned int ret = 0;
195 FRESULT res;
196
197 if ((res = f_write((FIL *)fp->exinf, data, len, &ret)) != FR_OK)
198 return -EIO;
199
200 return ret;
201}
202
203off_t file_seek(struct SHELL_FILE *fp, off_t ptr, int dir)
204{
205 switch (dir) {
206 case SEEK_SET:
207 dir = F_SEEK_SET;
208 break;
209 case SEEK_CUR:
210 dir = F_SEEK_CUR;
211 break;
212 case SEEK_END:
213 dir = F_SEEK_END;
214 break;
215 default:
216 return -EINVAL;
217 }
218
219 FRESULT res;
220 if ((res = f_seek((FIL *)fp->exinf, ptr, dir)) != FR_OK)
221 return -EIO;
222
223 return ((FIL *)fp->exinf)->fptr;
224}
225
226int file_ioctl(struct SHELL_FILE *fp, int req, void *arg)
227{
228 DRESULT res;
229
230 if ((res = disk_ioctl(((FIL *)fp->exinf)->fs->drv, req, arg) != RES_OK))
231 return -EINVAL;
232
233 return 0;
234}
235
236bool_t file_readable(struct SHELL_FILE *fp)
237{
238 return fp->readevt_w != fp->readevt_r;
239}
240
241void file_delete(struct SHELL_FILE *fp)
242{
243 free((FIL *)fp->exinf);
244 fp->exinf = NULL;
245}
246
247int shell_close(int fd)
248{
249 struct SHELL_FILE *fp = fd_to_fp(fd);
250 if (fp == NULL)
251 return -EBADF;
252
253 int ret = fp->type->close(fp);
254
255 delete_fp(fp);
256
257 return ret;
258}
259
260ssize_t shell_read(int fd, void *data, size_t len)
261{
262 struct SHELL_FILE *fp = fd_to_fp(fd);
263 if (fp == NULL)
264 return -EBADF;
265
266 return fp->type->read(fp, (unsigned char *)data, len);
267}
268
269int shell_readv(int fd, const struct iovec *iov, int iovcnt)
270{
271 int result = 0;
272 struct SHELL_FILE *fp = fd_to_fp(fd);
273 if (fp == NULL)
274 return -EBADF;
275
276 const struct iovec *end = &iov[iovcnt];
277 for (; iov < end; iov++) {
278 result += fp->type->read(fp, (unsigned char *)iov->iov_base, iov->iov_len);
279 }
280
281 return result;
282}
283
284ssize_t shell_write(int fd, const void *data, size_t len)
285{
286 struct SHELL_FILE *fp = fd_to_fp(fd);
287 if (fp == NULL)
288 return -EBADF;
289
290 return fp->type->write(fp, (unsigned char *)data, len);
291}
292
293int shell_writev(int fd, const struct iovec *iov, int iovcnt)
294{
295 int result = 0;
296 struct SHELL_FILE *fp = fd_to_fp(fd);
297 if (fp == NULL)
298 return -EBADF;
299
300 const struct iovec *end = &iov[iovcnt];
301 for (; iov < end; iov++) {
302 result += fp->type->write(fp, (unsigned char *)iov->iov_base, iov->iov_len);
303 }
304
305 return result;
306}
307
308int shell_llseek(int fd, off_t ptr, off_t *result, int dir)
309{
310 struct SHELL_FILE *fp = fd_to_fp(fd);
311 if (fp == NULL)
312 return -EBADF;
313
314 off_t ret = fp->type->seek(fp, ptr, dir);
315 if (ret < 0)
316 return ret;
317
318 *result = ret;
319 return 0;
320}
321
322int shell_fstat(int fd, struct stat * st)
323{
324 struct SHELL_FILE *fp = fd_to_fp(fd);
325 if (fp == NULL)
326 return -EBADF;
327
328 memset(st, 0, sizeof(*st));
329 st->st_mode = S_IFCHR;
330 //st->st_blksize = 1024;
331 return 0;
332}
333
334int shell_fsync(int fd)
335{
336 struct SHELL_FILE *fp = fd_to_fp(fd);
337 if (fp == NULL)
338 return -EBADF;
339 return -EIO;
340}
341
342int shell_ftruncate(int fd, off_t length)
343{
344 struct SHELL_FILE *fp = fd_to_fp(fd);
345 if (fp == NULL)
346 return -EBADF;
347
348 FRESULT res;
349 if ((res = f_truncate((FIL *)fp->exinf)) != FR_OK)
350 return fresult2errno(res);
351
352 return 0;
353}
354
355int shell_fcntl(int fd, int cmd, void *arg)
356{
357 return shell_ioctl(fd, cmd, arg);
358}
359
360extern IO_TYPE IO_TYPE_SIO;
361
362int sio_tcgetattr(int fd, struct termios *termios)
363{
364 struct SHELL_FILE *fp = fd_to_fp(fd);
365 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO))
366 return -EBADF;
367
368 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
369
370 memset(termios, 0, sizeof(*termios));
371
372 if (ntstdio->option & NTSTDIO_OPTION_LINE_ECHO) {
373 termios->c_lflag |= ECHO;
374 }
375 else {
376 termios->c_lflag &= ~ECHO;
377 }
378 if (ntstdio->option & NTSTDIO_OPTION_CANON) {
379 termios->c_lflag |= ICANON;
380 }
381 else {
382 termios->c_lflag &= ~ICANON;
383 }
384 if (ntstdio->option & NTSTDIO_OPTION_LF_CR) {
385 termios->c_iflag |= INLCR;
386 }
387 else {
388 termios->c_iflag &= ~INLCR;
389 }
390 if (ntstdio->option & NTSTDIO_OPTION_LF_CRLF) {
391 termios->c_oflag |= ONLCR;
392 }
393 else {
394 termios->c_oflag &= ~ONLCR;
395 }
396
397 return 0;
398}
399
400int sio_tcsetattr(int fd, int optional_actions, const struct termios *termios)
401{
402 struct SHELL_FILE *fp = fd_to_fp(fd);
403 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO))
404 return -EBADF;
405
406 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
407
408 if (optional_actions == TCSANOW) {
409 if (termios->c_lflag & ECHO) {
410 ntstdio->option |= NTSTDIO_OPTION_LINE_ECHO;
411 }
412 else {
413 ntstdio->option &= ~NTSTDIO_OPTION_LINE_ECHO;
414 }
415 if (termios->c_lflag & ICANON) {
416 ntstdio->option |= NTSTDIO_OPTION_CANON;
417 }
418 else {
419 ntstdio->option &= ~NTSTDIO_OPTION_CANON;
420 }
421 if (termios->c_iflag & INLCR) {
422 ntstdio->option |= NTSTDIO_OPTION_LF_CR;
423 }
424 else {
425 ntstdio->option &= ~NTSTDIO_OPTION_LF_CR;
426 }
427 if (termios->c_oflag & ONLCR) {
428 ntstdio->option |= NTSTDIO_OPTION_LF_CRLF;
429 }
430 else {
431 ntstdio->option &= ~NTSTDIO_OPTION_LF_CRLF;
432 }
433 return 0;
434 }
435
436 shell_abort();
437 return 0;
438}
439
440int shell_stat(const char *__restrict path, struct stat *__restrict st)
441{
442 FILINFO fi;
443 FRESULT ret;
444#if FF_USE_LFN
445 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
446 fi.lfname = lfn;
447 fi.lfsize = sizeof lfn;
448#endif
449 if (strcmp(path, ".") == 0) {
450 char cwd[FF_MAX_LFN];
451 if ((ret = f_getcwd(cwd, sizeof(cwd))) != FR_OK) {
452 return fresult2errno(ret);
453 }
454 int l = strlen(cwd);
455 // ルートディレクトリの場合
456 if (cwd[l - 2] == ':' && cwd[l - 1] == '/') {
457 st->st_size = 0;
458 st->st_mtim.tv_nsec = 0;
459 st->st_mtim.tv_sec = 0;
460 st->st_mode = S_IFDIR;
461 return 0;
462 }
463 if ((ret = f_stat(cwd, &fi)) != FR_OK) {
464 return fresult2errno(ret);
465 }
466 }
467 else if ((ret = f_stat(path, &fi)) != FR_OK) {
468 return fresult2errno(ret);
469 }
470
471 st->st_size = fi.fsize;
472 st->st_mtim.tv_nsec = 0;
473 st->st_mtim.tv_sec = fi.fdate + fi.ftime;
474 st->st_mode = (S_IRUSR | S_IRGRP | S_IROTH);
475 st->st_mode |= (fi.fattrib & AM_RDO) ? 0 : (S_IWUSR | S_IWGRP | S_IWOTH);
476 st->st_mode |= (fi.fattrib & (AM_DIR | AM_VOL)) ? S_IFDIR : S_IFREG;
477
478 return 0;
479}
480
481int shell_lstat(const char *__restrict path, struct stat *__restrict st)
482{
483 return shell_stat(path, st);
484}
485
486int shell_link(const char *a, const char *b)
487{
488 return -EPERM;
489}
490
491int shell_unlink(const char *path)
492{
493 FRESULT res;
494
495 if ((res = f_unlink(path)) != FR_OK)
496 return -EIO;
497
498 return 0;
499}
500
501int shell_rmdir(const char *path)
502{
503 FRESULT res;
504
505 if ((res = f_unlink(path)) != FR_OK)
506 return -EIO;
507
508 return 0;
509}
510
511int shell_rename(const char *oldpath, const char *newpath)
512{
513 FRESULT res;
514
515 if ((res = f_rename(oldpath, newpath)) != FR_OK)
516 return fresult2errno(res);
517 return 0;
518}
519
520#define S_IREAD S_IRUSR
521#define S_IWRITE S_IWUSR
522
523int shell_mkdir(const char *path, mode_t mode)
524{
525 FRESULT res;
526
527 if ((res = f_mkdir(path)) != FR_OK)
528 return fresult2errno(res);
529
530 BYTE attr = 0;
531 BYTE mask = AM_RDO | AM_SYS; // AM_ARC, AM_HID
532
533 if (mode & S_IREAD) {
534 if ((mode & S_IWRITE) == 0) {
535 attr |= AM_RDO;
536 }
537 }
538 else {
539 attr |= AM_SYS;
540 }
541
542 if ((res = f_chmod(path, attr, mask)) != FR_OK) {
543 return fresult2errno(res);
544 }
545
546 return 0;
547}
548
549int shell_chmod(const char *path, mode_t mode)
550{
551 FRESULT res;
552 BYTE attr = 0;
553 BYTE mask = AM_RDO | AM_SYS; // AM_ARC, AM_HID
554
555 if (mode & S_IREAD) {
556 if ((mode & S_IWRITE) == 0) {
557 attr |= AM_RDO;
558 }
559 }
560 else {
561 attr |= AM_SYS;
562 }
563
564 if ((res = f_chmod(path, attr, mask)) != FR_OK) {
565 return fresult2errno(res);
566 }
567
568 return 0;
569}
570
571char *shell_getcwd(char *buf, size_t size)
572{
573 FRESULT ret;
574 if ((ret = f_getcwd(buf, size)) != FR_OK) {
575 return NULL;
576 }
577
578 return buf;
579}
580
581int shell_chdir(const char *path)
582{
583 FRESULT res;
584 if ((res = f_chdir(path)) != FR_OK) {
585 return fresult2errno(res);
586 }
587
588 return 0;
589}
590
591int shell_chroot(const char *path)
592{
593 shell_abort();
594 return -EPERM;
595}
596
597int dir_close(struct SHELL_FILE *fp)
598{
599 FRESULT res;
600 if ((res = f_closedir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
601 return fresult2errno(res);
602 }
603
604 return 0;
605}
606
607int shell_getdents(int fd, struct dirent *de, size_t len)
608{
609 if (len < sizeof(struct dirent))
610 return -EINVAL;
611
612 struct SHELL_FILE *fp = fd_to_fp(fd);
613 if (fp == NULL)
614 return -EBADF;
615
616 FILINFO fno;
617#if FF_USE_LFN
618 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
619 fno.lfname = lfn;
620 fno.lfsize = sizeof lfn;
621#endif
622 FRESULT res;
623 if ((res = f_readdir(&((struct SHELL_DIR *)fp->exinf)->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
624 return fresult2errno(res);
625 }
626
627 memset(de, 0, sizeof(*de));
628#if FF_USE_LFN
629 ntlibc_strlcpy(de->d_name, *fno.lfname ? fno.lfname : fno.fname, sizeof(de->d_name));
630#else
631 ntlibc_strlcpy(de->d_name, fno.fname, sizeof(de->d_name));
632#endif
633
634 return 0;
635}
636
637size_t dir_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
638{
639 return -EPERM;
640}
641
642size_t dir_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
643{
644 return -EPERM;
645}
646
647off_t dir_seek(struct SHELL_FILE *fp, off_t ptr, int dir)
648{
649 FRESULT res;
650
651 if (dir != SEEK_SET)
652 return -EINVAL;
653
654 if (ptr == 0) {
655 if ((res = f_rewinddir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
656 return fresult2errno(res);
657 }
658 }
659 else {
660 FILINFO fno;
661#if FF_USE_LFN
662 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
663 fno.lfname = lfn;
664 fno.lfsize = sizeof lfn;
665#endif
666 if ((res = f_rewinddir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
667 return fresult2errno(res);
668 }
669
670 for (int i = 0; i < ptr; i++) {
671 if ((res = f_readdir(&((struct SHELL_DIR *)fp->exinf)->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
672 return fresult2errno(res);
673 }
674 }
675 }
676
677 return ptr;
678}
679
680int dir_ioctl(struct SHELL_FILE *fp, int req, void *arg)
681{
682 return -EINVAL;
683}
684
685bool_t dir_readable(struct SHELL_FILE *fp)
686{
687 return fp->readevt_w != fp->readevt_r;
688}
689
690void dir_delete(struct SHELL_FILE *fp)
691{
692 free((struct SHELL_DIR *)fp->exinf);
693 fp->exinf = NULL;
694}
695
696pid_t shell_getpid(void)
697{
698 return 1;
699}
700
701int shell_access(const char *path, int mode)
702{
703 struct stat st;
704 int ret;
705
706 ret = shell_stat(path, &st);
707 if (ret != 0)
708 return ret;
709
710 return 0;
711}
712
713#ifndef _MSC_VER
714extern uint32_t __HeapBase;
715extern uint32_t __HeapLimit;
716#else
717uint8_t __HeapBase[14 * 4096];
718#define __HeapLimit __HeapBase[sizeof(__HeapBase)]
719#endif
720
721void *shell_brk(void *addr)
722{
723 if (addr == 0) {
724 return (void *)(&__HeapBase);
725 }
726 if ((addr >= (void *)&__HeapBase) && (addr < (void *)&__HeapLimit)) {
727 return addr;
728 }
729 return (void *)-1;
730}
731
732void *shell_mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoffset)
733{
734 if (fd != -1)
735 return (void *)-EINVAL;
736
737 if ((length >= 0) && (length <= sizeof(&__HeapBase))) {
738 return &__HeapBase;
739 }
740 return (void *)-1;
741}
742
743int shell_mprotect(void *addr, size_t len, int prot)
744{
745 //if ((addr >= (void *)&__HeapBase) && (addr + len < (void *)&__HeapLimit)) {
746 return 0;
747//}
748//return -1;
749}
Note: See TracBrowser for help on using the repository browser.