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

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

ntshellアプリはnewlibを使うよう変更し、syscallの実装部分と区別がつくよう更新。

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