source: EcnlProtoTool/trunk/ntshell/src/io_stub.c@ 441

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

NTShellタスクを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 12.8 KB
RevLine 
[286]1/*
[434]2 * TOPPERS PROJECT Home Network Working Group Software
[441]3 *
[434]4 * Copyright (C) 2017-2019 Cores Co., Ltd. Japan
[441]5 *
[286]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 * 免責すること.
[441]28 *
[286]29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
[441]34 *
[286]35 * @(#) $Id$
36 */
[331]37#include "shellif.h"
[279]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>
[441]44#include <string.h>
45#include "syssvc/serial.h"
[279]46#include "syssvc/syslog.h"
[433]47#include "fdtable.h"
[331]48#include "util/ntstdio.h"
49#include "usrcmd.h"
50#include "core/ntlibc.h"
[441]51#include "kernel_cfg.h"
52#include "target_syssvc.h"
[279]53
[441]54struct SHELL_DIR {
55 FATFS_DIR dir;
56 struct dirent dirent;
57};
58
[331]59int fresult2errno(FRESULT res)
[279]60{
[331]61 switch (res) {
62 case FR_INVALID_OBJECT:
63 return -EINVAL;
64 case FR_TOO_MANY_OPEN_FILES:
65 return -ENOMEM;
66 case FR_NO_FILE:
67 case FR_NO_PATH:
68 case FR_INVALID_DRIVE:
69 case FR_INVALID_NAME:
70 return -ENOENT;
71 case FR_DISK_ERR:
72 case FR_NO_FILESYSTEM:
73 case FR_NOT_ENABLED:
74 return -ENODEV;
75 case FR_WRITE_PROTECTED:
76 case FR_DENIED:
77 return -EACCES;
78 case FR_EXIST:
79 return -EEXIST;
80 case FR_INT_ERR:
81 default:
82 return -EIO;
83 }
84}
85
[441]86static int file_close(struct SHELL_FILE *fp);
87static size_t file_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
88static size_t file_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
89static off_t file_seek(struct SHELL_FILE *fp, off_t ofs, int org);
90static int file_ioctl(struct SHELL_FILE *fp, int req, void *arg);
91static bool_t file_readable(struct SHELL_FILE *fp);
92static bool_t file_writable(struct SHELL_FILE *fp);
93static void file_delete(struct SHELL_FILE *fp);
94
95static int dir_close(struct SHELL_FILE *fp);
96static size_t dir_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
97static size_t dir_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
98static off_t dir_seek(struct SHELL_FILE *fp, off_t ofs, int org);
99static int dir_ioctl(struct SHELL_FILE *fp, int req, void *arg);
100static bool_t dir_readable(struct SHELL_FILE *fp);
101static bool_t dir_writable(struct SHELL_FILE *fp);
102static void dir_delete(struct SHELL_FILE *fp);
103
104IO_TYPE IO_TYPE_FILE = { file_close, file_read, file_write, file_seek, file_ioctl, file_readable, file_writable, file_delete };
105IO_TYPE IO_TYPE_DIR = { dir_close, dir_read, dir_write, dir_seek, dir_ioctl, dir_readable, dir_writable, dir_delete };
106
107int shell_open(const char *path, int flags, void *arg)
[331]108{
[279]109 FRESULT res;
[441]110 struct SHELL_FILE *fp;
[279]111
[331]112 if (flags & O_DIRECTORY) {
[441]113 fp = new_fp(&IO_TYPE_DIR, 0, 0);
[331]114 if (fp == NULL)
115 return -ENOMEM;
116
[441]117 fp->exinf = malloc(sizeof(struct SHELL_DIR));
118 memset(fp->exinf, 0, sizeof(struct SHELL_DIR));
119
120 FATFS_DIR *dir = &((struct SHELL_DIR *)fp->exinf)->dir;
[331]121 if ((res = f_opendir(dir, path)) != FR_OK) {
[441]122 delete_fp(fp);
[331]123 return fresult2errno(res);
124 }
125 return 0;
126 }
127
[441]128 fp = new_fp(&IO_TYPE_FILE, 0, 1);
[279]129 if (fp == NULL)
[331]130 return -ENOMEM;
[279]131
[441]132 fp->exinf = malloc(sizeof(FIL));
133 memset(fp->exinf, 0, sizeof(FIL));
134
[279]135 BYTE fmd = 0;
136 switch (flags & O_ACCMODE) {
137 case O_RDONLY:
138 fmd = FA_READ;
139 break;
140 case O_WRONLY:
141 fmd = FA_WRITE;
142 break;
143 default:
144 fmd = FA_READ | FA_WRITE;
145 break;
146 }
147 /* ファイルを作成 */
148 if (flags & O_CREAT) {
149 /* 既存の内容は消す */
150 if (flags & O_TRUNC) {
151 fmd |= FA_CREATE_ALWAYS;
152 }
153 /* 新規作成の保障 */
154 else if (flags & O_EXCL) {
155 fmd |= FA_CREATE_NEW;
156 }
157 else {
158 fmd |= FA_OPEN_ALWAYS;
159 }
160 }
161 /* ある場合は開く */
162 else {
163 /* 既存の内容は消す */
164 if (flags & O_TRUNC) {
165 fmd |= FA_CREATE_ALWAYS;
166 }
167 }
168
[441]169 if ((res = f_open((FIL *)fp->exinf, path, fmd)) == FR_OK) {
[279]170 fp->handle = fp->fd;
171 return fp->fd;
172 }
173
[441]174 delete_fp(fp);
[331]175 return fresult2errno(res);
[279]176}
177
[441]178int file_close(struct SHELL_FILE *fp)
[279]179{
180 FRESULT res;
181
[441]182 if ((res = f_close((FIL *)fp->exinf)) == FR_OK) {
[279]183 return 0;
184 }
185
[331]186 return -EINVAL;
[279]187}
188
[441]189size_t file_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
[279]190{
191 unsigned int ret = 0;
192 FRESULT res;
193
[441]194 if ((res = f_read((FIL *)fp->exinf, data, len, &ret)) != FR_OK)
[331]195 return -EIO;
[279]196
197 return ret;
198}
199
[441]200size_t file_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
[279]201{
202 unsigned int ret = 0;
203 FRESULT res;
204
[441]205 if ((res = f_write((FIL *)fp->exinf, data, len, &ret)) != FR_OK)
[331]206 return -EIO;
[279]207
208 return ret;
209}
210
[441]211off_t file_seek(struct SHELL_FILE *fp, off_t ptr, int dir)
[331]212{
213 switch (dir) {
214 case SEEK_SET:
215 dir = F_SEEK_SET;
216 break;
217 case SEEK_CUR:
218 dir = F_SEEK_CUR;
219 break;
220 case SEEK_END:
221 dir = F_SEEK_END;
222 break;
223 default:
224 return -EINVAL;
225 }
226
227 FRESULT res;
[441]228 if ((res = f_seek((FIL *)fp->exinf, ptr, dir)) != FR_OK)
[331]229 return -EIO;
230
[441]231 return ((FIL *)fp->exinf)->fptr;
[331]232}
233
[441]234int file_ioctl(struct SHELL_FILE *fp, int req, void *arg)
[331]235{
236 DRESULT res;
237
[441]238 if ((res = disk_ioctl(((FIL *)fp->exinf)->fs->drv, req, arg) != RES_OK))
[331]239 return -EINVAL;
240
241 return 0;
242}
243
[441]244bool_t file_readable(struct SHELL_FILE *fp)
[279]245{
[441]246 return fp->readevt_w != fp->readevt_r;
[279]247}
248
[441]249bool_t file_writable(struct SHELL_FILE *fp)
[279]250{
[441]251 return fp->writable && (fp->writeevt_w == fp->writeevt_r);
[279]252}
253
[441]254void file_delete(struct SHELL_FILE *fp)
[279]255{
[441]256 free((FIL *)fp->exinf);
257 fp->exinf = NULL;
[331]258}
259
[279]260int shell_fstat(int fd, struct stat * st)
261{
[441]262 struct SHELL_FILE *fp = fd_to_fp(fd);
[279]263 if (fp == NULL)
[331]264 return -EBADF;
[279]265
266 memset(st, 0, sizeof(*st));
267 st->st_mode = S_IFCHR;
268 //st->st_blksize = 1024;
269 return 0;
270}
271
[331]272int shell_fsync(int fd)
[279]273{
[441]274 struct SHELL_FILE *fp = fd_to_fp(fd);
[279]275 if (fp == NULL)
[331]276 return -EBADF;
277 return -EIO;
[279]278}
279
[331]280int shell_ftruncate(int fd, off_t length)
[279]281{
[441]282 struct SHELL_FILE *fp = fd_to_fp(fd);
[279]283 if (fp == NULL)
[331]284 return -EBADF;
[279]285
286 FRESULT res;
[441]287 if ((res = f_truncate((FIL *)fp->exinf)) != FR_OK)
[331]288 return fresult2errno(res);
[279]289
290 return 0;
291}
292
[331]293int shell_fcntl(int fd, int cmd, void *arg)
[279]294{
[331]295 return shell_ioctl(fd, cmd, arg);
[279]296}
297
[441]298int shell_stat(const char *restrict path, struct stat *restrict st)
[279]299{
300 FILINFO fi;
301 FRESULT ret;
[434]302#if FF_USE_LFN
303 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
[279]304 fi.lfname = lfn;
305 fi.lfsize = sizeof lfn;
306#endif
[331]307 if (ntlibc_strcmp(path, ".") == 0) {
[434]308 char cwd[FF_MAX_LFN];
[279]309 if ((ret = f_getcwd(cwd, sizeof(cwd))) != FR_OK) {
[331]310 return fresult2errno(ret);
[279]311 }
[331]312 int l = ntlibc_strlen(cwd);
[279]313 // ルートディレクトリの場合
314 if (cwd[l - 2] == ':' && cwd[l - 1] == '/') {
315 st->st_size = 0;
[331]316 st->st_mtim.tv_nsec = 0;
317 st->st_mtim.tv_sec = 0;
[279]318 st->st_mode = S_IFDIR;
319 return 0;
320 }
321 if ((ret = f_stat(cwd, &fi)) != FR_OK) {
[331]322 return fresult2errno(ret);
[279]323 }
324 }
325 else if ((ret = f_stat(path, &fi)) != FR_OK) {
[331]326 return fresult2errno(ret);
[279]327 }
328
329 st->st_size = fi.fsize;
[331]330 st->st_mtim.tv_nsec = 0;
[441]331 st->st_mtim.tv_sec = (time_t)fi.fdate + (time_t)fi.ftime;
332 st->st_mode = (S_IRUSR | S_IRGRP | S_IROTH);
[279]333 st->st_mode |= (fi.fattrib & AM_RDO) ? 0 : (S_IWUSR | S_IWGRP | S_IWOTH);
334 st->st_mode |= (fi.fattrib & (AM_DIR | AM_VOL)) ? S_IFDIR : S_IFREG;
335
336 return 0;
337}
338
[441]339int shell_lstat(const char *restrict path, struct stat *restrict st)
[279]340{
[331]341 return shell_stat(path, st);
[279]342}
343
[331]344int shell_link(const char *a, const char *b)
345{
346 return -EPERM;
347}
348
[279]349int shell_unlink(const char *path)
350{
351 FRESULT res;
352
353 if ((res = f_unlink(path)) != FR_OK)
[331]354 return -EIO;
[279]355
356 return 0;
357}
358
[331]359int shell_rmdir(const char *path)
[279]360{
361 FRESULT res;
362
363 if ((res = f_unlink(path)) != FR_OK)
[331]364 return -EIO;
[279]365
366 return 0;
367}
368
369int shell_rename(const char *oldpath, const char *newpath)
370{
371 FRESULT res;
372
373 if ((res = f_rename(oldpath, newpath)) != FR_OK)
[331]374 return fresult2errno(res);
[279]375 return 0;
376}
377
[331]378#define S_IREAD S_IRUSR
379#define S_IWRITE S_IWUSR
380
381int shell_mkdir(const char *path, mode_t mode)
[279]382{
383 FRESULT res;
384
385 if ((res = f_mkdir(path)) != FR_OK)
[331]386 return fresult2errno(res);
[279]387
388 BYTE attr = 0;
389 BYTE mask = AM_RDO | AM_SYS; // AM_ARC, AM_HID
390
[441]391 if (mode & S_IREAD) {
392 if ((mode & S_IWRITE) == 0) {
[279]393 attr |= AM_RDO;
394 }
395 }
396 else {
397 attr |= AM_SYS;
398 }
399
[441]400 if ((res = f_chmod(path, attr, mask)) != FR_OK) {
[331]401 return fresult2errno(res);
[279]402 }
403
404 return 0;
405}
406
[331]407int shell_chmod(const char *path, mode_t mode)
[279]408{
[331]409 FRESULT res;
[279]410 BYTE attr = 0;
411 BYTE mask = AM_RDO | AM_SYS; // AM_ARC, AM_HID
412
[441]413 if (mode & S_IREAD) {
414 if ((mode & S_IWRITE) == 0) {
[279]415 attr |= AM_RDO;
416 }
417 }
418 else {
419 attr |= AM_SYS;
420 }
421
[441]422 if ((res = f_chmod(path, attr, mask)) != FR_OK) {
[331]423 return fresult2errno(res);
[279]424 }
425
426 return 0;
427}
428
[331]429char *shell_getcwd(char *buf, size_t size)
[279]430{
431 FRESULT ret;
[441]432 if ((ret = f_getcwd(buf, size)) != FR_OK) {
[279]433 return NULL;
434 }
435
436 return buf;
437}
438
[331]439int shell_chdir(const char *path)
[279]440{
[331]441 FRESULT res;
442 if ((res = f_chdir(path)) != FR_OK) {
443 return fresult2errno(res);
[279]444 }
445
446 return 0;
447}
448
[331]449int shell_chroot(const char *path)
[279]450{
[331]451 shell_abort();
452 return -EPERM;
[279]453}
454
[441]455int dir_close(struct SHELL_FILE *fp)
[279]456{
[331]457 FRESULT res;
[441]458 if ((res = f_closedir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
[331]459 return fresult2errno(res);
[279]460 }
461
[331]462 return 0;
[279]463}
464
[331]465int shell_getdents(int fd, struct dirent *de, size_t len)
[279]466{
[331]467 if (len < sizeof(struct dirent))
468 return -EINVAL;
[279]469
[441]470 struct SHELL_FILE *fp = fd_to_fp(fd);
[331]471 if (fp == NULL)
472 return -EBADF;
[279]473
474 FILINFO fno;
[434]475#if FF_USE_LFN
476 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
[279]477 fno.lfname = lfn;
478 fno.lfsize = sizeof lfn;
479#endif
[331]480 FRESULT res;
[441]481 if ((res = f_readdir(&((struct SHELL_DIR *)fp->exinf)->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
[331]482 return fresult2errno(res);
[279]483 }
484
485 memset(de, 0, sizeof(*de));
[434]486#if FF_USE_LFN
[331]487 ntlibc_strlcpy(de->d_name, *fno.lfname ? fno.lfname : fno.fname, sizeof(de->d_name));
[279]488#else
[331]489 ntlibc_strlcpy(de->d_name, fno.fname, sizeof(de->d_name));
[279]490#endif
491
[331]492 return 0;
[279]493}
494
[441]495size_t dir_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
[279]496{
[331]497 return -EPERM;
498}
499
[441]500size_t dir_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
[331]501{
502 return -EPERM;
503}
504
[441]505off_t dir_seek(struct SHELL_FILE *fp, off_t ptr, int dir)
[331]506{
507 FRESULT res;
508
509 if (dir != SEEK_SET)
510 return -EINVAL;
511
512 if (ptr == 0) {
[441]513 if ((res = f_rewinddir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
[331]514 return fresult2errno(res);
515 }
[279]516 }
[331]517 else {
518 FILINFO fno;
[434]519#if FF_USE_LFN
520 static char lfn[FF_MAX_LFN + 1]; /* Buffer to store the LFN */
[331]521 fno.lfname = lfn;
522 fno.lfsize = sizeof lfn;
523#endif
[441]524 if ((res = f_rewinddir(&((struct SHELL_DIR *)fp->exinf)->dir)) != FR_OK) {
[331]525 return fresult2errno(res);
526 }
527
528 for (int i = 0; i < ptr; i++) {
[441]529 if ((res = f_readdir(&((struct SHELL_DIR *)fp->exinf)->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
[331]530 return fresult2errno(res);
531 }
532 }
533 }
534
535 return ptr;
[279]536}
537
[441]538int dir_ioctl(struct SHELL_FILE *fp, int req, void *arg)
[279]539{
[331]540 return -EINVAL;
[279]541}
542
[441]543bool_t dir_readable(struct SHELL_FILE *fp)
544{
545 return fp->readevt_w != fp->readevt_r;
546}
547
548bool_t dir_writable(struct SHELL_FILE *fp)
549{
550 return false;
551}
552
553void dir_delete(struct SHELL_FILE *fp)
554{
555 free((struct SHELL_DIR *)fp->exinf);
556 fp->exinf = NULL;
557}
558
[331]559pid_t shell_getpid(void)
[279]560{
[331]561 return 1;
562}
563
564int shell_access(const char *path, int mode)
565{
566 struct stat st;
567 int ret;
568
569 ret = shell_stat(path, &st);
570 if (ret != 0)
571 return ret;
572
[279]573 return 0;
574}
Note: See TracBrowser for help on using the repository browser.