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

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

ファイルディスクリプタ処理を更新

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