Index: EcnlProtoTool/trunk/ntshell/src/io_stub.c
===================================================================
--- EcnlProtoTool/trunk/ntshell/src/io_stub.c	(revision 321)
+++ EcnlProtoTool/trunk/ntshell/src/io_stub.c	(revision 331)
@@ -35,9 +35,6 @@
  *  @(#) $Id$
  */
+#include "shellif.h"
 #include <stdint.h>
-#include <stdio.h>
-#include <sys/unistd.h>
-#include <limits.h>
-#include <fcntl.h>
 #include "ff.h"
 #include <kernel.h>
@@ -45,7 +42,5 @@
 #include <t_stdlib.h>
 #include <sil.h>
-#include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <setjmp.h>
 #include "syssvc/syslog.h"
@@ -61,18 +56,59 @@
 #include <net/if_var.h>
 #include <netinet/udp_var.h>
-#include <ethernet_api.h>
-#include "ff.h"
+//#include <ethernet_api.h>
 #include "socket_stub.h"
-#include "../../../musl-1.1.12/include/_dirent.h"
-#include "../../../musl-1.1.12/include/_termios.h"
-#include "ntstdio.h"
-
-int shell_open(const char * path, int flags)
-{
-	FRESULT res;
-
-	struct _IO_FILE *fp = new_file_fd(0);
-	if (fp == NULL)
-		return -1;
+//#include <sys/stat.h>
+#include "util/ntstdio.h"
+#include "usrcmd.h"
+#include "core/ntlibc.h"
+
+int fresult2errno(FRESULT res)
+{
+	switch (res) {
+	case FR_INVALID_OBJECT:
+		return -EINVAL;
+	case FR_TOO_MANY_OPEN_FILES:
+		return -ENOMEM;
+	case FR_NO_FILE:
+	case FR_NO_PATH:
+	case FR_INVALID_DRIVE:
+	case FR_INVALID_NAME:
+		return -ENOENT;
+	case FR_DISK_ERR:
+	case FR_NO_FILESYSTEM:
+	case FR_NOT_ENABLED:
+		return -ENODEV;
+	case FR_WRITE_PROTECTED:
+	case FR_DENIED:
+		return -EACCES;
+	case FR_EXIST:
+		return -EEXIST;
+	case FR_INT_ERR:
+	default:
+		return -EIO;
+	}
+}
+
+int shell_open(const char * path, int flags, void *arg)
+{
+	FRESULT res;
+	struct _IO_FILE *fp;
+
+	if (flags & O_DIRECTORY) {
+		fp = new_dir_fd(0);
+		if (fp == NULL)
+			return -ENOMEM;
+
+		DIR *dir = &fp->dir;
+		FRESULT res;
+		if ((res = f_opendir(dir, path)) != FR_OK) {
+			return fresult2errno(res);
+		}
+		return 0;
+	}
+
+	fp = new_file_fd(0);
+	if (fp == NULL)
+		return -ENOMEM;
 
 	BYTE fmd = 0;
@@ -115,5 +151,5 @@
 	}
 
-	return -1;
+	return fresult2errno(res);
 }
 
@@ -126,5 +162,5 @@
 	}
 
-	return -1;
+	return -EINVAL;
 }
 
@@ -135,5 +171,5 @@
 
 	if ((res = f_read(&fp->file, data, len, &ret)) != FR_OK)
-		return -1;
+		return -EIO;
 
 	return ret;
@@ -146,47 +182,111 @@
 
 	if ((res = f_write(&fp->file, data, len, &ret)) != FR_OK)
-		return -1;
+		return -EIO;
 
 	return ret;
 }
 
+off_t file_seek(struct _IO_FILE *fp, off_t ptr, int dir)
+{
+	switch (dir) {
+	case SEEK_SET:
+		dir = F_SEEK_SET;
+		break;
+	case SEEK_CUR:
+		dir = F_SEEK_CUR;
+		break;
+	case SEEK_END:
+		dir = F_SEEK_END;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	FRESULT res;
+	if ((res = f_seek(&fp->file, ptr, dir)) != FR_OK)
+		return -EIO;
+
+	return fp->file.fptr;
+}
+
+int file_ioctl(struct _IO_FILE *fp, int req, void *arg)
+{
+	DRESULT res;
+
+	if ((res = disk_ioctl(fp->file.fs->drv, req, arg) != RES_OK))
+		return -EINVAL;
+
+	return 0;
+}
+
 int shell_close(int fd)
 {
 	struct _IO_FILE *fp = fd_to_fp(fd);
 	if (fp == NULL)
-		return -1;
+		return -EBADF;
 
 	return fp->close(fp);
 }
 
-int shell_read(int fd, char *data, int len)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
+ssize_t shell_read(int fd, void *data, size_t len)
+{
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
 
 	return fp->read(fp, (unsigned char *)data, len);
 }
 
-int shell_write(int fd, char *data, int len)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
+int shell_readv(int fd, const struct iovec *iov, int iovcnt)
+{
+	int result = 0;
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
+
+	const struct iovec *end = &iov[iovcnt];
+	for (; iov < end; iov++) {
+		result += fp->read(fp, (unsigned char *)iov->iov_base, iov->iov_len);
+	}
+
+	return result;
+}
+
+ssize_t shell_write(int fd, const void *data, size_t len)
+{
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
 
 	return fp->write(fp, (unsigned char *)data, len);
 }
 
-int shell_lseek(int fd, int ptr, int dir)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
-
-	FRESULT res;
-	if ((res = f_seek(&fp->file, ptr, dir)) != FR_OK)
-		return -1;
-
-	return fp->file.fptr;
+int shell_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+	int result = 0;
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
+
+	const struct iovec *end = &iov[iovcnt];
+	for (; iov < end; iov++) {
+		result += fp->write(fp, (unsigned char *)iov->iov_base, iov->iov_len);
+	}
+
+	return result;
+}
+
+int shell_llseek(int fd, off_t ptr, off_t *result, int dir)
+{
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
+
+	off_t ret = fp->seek(fp, ptr, dir);
+	if (ret < 0)
+		return ret;
+
+	*result = ret;
+	return 0;
 }
 
@@ -195,5 +295,5 @@
 	struct _IO_FILE *fp = fd_to_fp(fd);
 	if (fp == NULL)
-		return -1;
+		return -EBADF;
 
 	memset(st, 0, sizeof(*st));
@@ -203,34 +303,31 @@
 }
 
-int fsync(int fd)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
-	return -1;
-}
-
-int ftruncate(int fd, off_t length)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
+int shell_fsync(int fd)
+{
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
+	return -EIO;
+}
+
+int shell_ftruncate(int fd, off_t length)
+{
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
 
 	FRESULT res;
 	if ((res = f_truncate(&fp->file)) != FR_OK)
-		return -1;
-
-	return 0;
-}
-
-int ioctl(int fd, int request, va_list ap)
-{
-	struct _IO_FILE *fp = fd_to_fp(fd);
-	if (fp == NULL)
-		return -1;
-	return -1;
-}
-
-int tcgetattr(int fd, struct termios *termios)
+		return fresult2errno(res);
+
+	return 0;
+}
+
+int shell_fcntl(int fd, int cmd, void *arg)
+{
+	return shell_ioctl(fd, cmd, arg);
+}
+
+int sio_tcgetattr(int fd, struct termios *termios)
 {
 	extern ntstdio_t ntstdio;
@@ -265,9 +362,9 @@
 		return 0;
 	}
-	abort();
-	return 0;
-}
-
-int tcsetattr(int fd, int optional_actions, const struct termios *termios)
+	shell_abort();
+	return 0;
+}
+
+int sio_tcsetattr(int fd, int optional_actions, const struct termios *termios)
 {
 	extern ntstdio_t ntstdio;
@@ -300,9 +397,9 @@
 		return 0;
 	}
-	abort();
-	return 0;
-}
-
-int shell_stat(const char *path, struct stat *st)
+	shell_abort();
+	return 0;
+}
+
+int shell_stat(const char *__restrict path, struct stat *__restrict st)
 {
 	FILINFO fi;
@@ -313,27 +410,29 @@
 	fi.lfsize = sizeof lfn;
 #endif
-	if (strcmp(path, ".") == 0) {
+	if (ntlibc_strcmp(path, ".") == 0) {
 		char cwd[_MAX_LFN];
 		if ((ret = f_getcwd(cwd, sizeof(cwd))) != FR_OK) {
-		return -1;
-		}
-		int l = strlen(cwd);
+			return fresult2errno(ret);
+		}
+		int l = ntlibc_strlen(cwd);
 		// ルートディレクトリの場合
 		if (cwd[l - 2] == ':' && cwd[l - 1] == '/') {
 			st->st_size = 0;
-			st->st_mtime = 0;
+			st->st_mtim.tv_nsec = 0;
+			st->st_mtim.tv_sec = 0;
 			st->st_mode = S_IFDIR;
 			return 0;
 		}
 		if ((ret = f_stat(cwd, &fi)) != FR_OK) {
-			return -1;
+			return fresult2errno(ret);
 		}
 	}
 	else if ((ret = f_stat(path, &fi)) != FR_OK) {
-		return -1;
+		return fresult2errno(ret);
 	}
 
 	st->st_size = fi.fsize;
-	st->st_mtime = fi.fdate + fi.ftime;
+	st->st_mtim.tv_nsec = 0;
+	st->st_mtim.tv_sec = fi.fdate + fi.ftime;
 	st->st_mode  = (S_IRUSR | S_IRGRP | S_IROTH);
 	st->st_mode |= (fi.fattrib & AM_RDO) ? 0 : (S_IWUSR | S_IWGRP | S_IWOTH);
@@ -343,7 +442,12 @@
 }
 
-int shell_link(void)
-{
-	return -1;
+int shell_lstat(const char *__restrict path, struct stat *__restrict st)
+{
+	return shell_stat(path, st);
+}
+
+int shell_link(const char *a, const char *b)
+{
+	return -EPERM;
 }
 
@@ -353,15 +457,15 @@
 
 	if ((res = f_unlink(path)) != FR_OK)
-		return -1;
-
-	return 0;
-}
-
-int rmdir(const char *path)
+		return -EIO;
+
+	return 0;
+}
+
+int shell_rmdir(const char *path)
 {
 	FRESULT res;
 
 	if ((res = f_unlink(path)) != FR_OK)
-		return -1;
+		return -EIO;
 
 	return 0;
@@ -373,14 +477,17 @@
 
 	if ((res = f_rename(oldpath, newpath)) != FR_OK)
-		return -1;
-	return 0;
-}
-
-int mkdir(const char *path, mode_t mode)
+		return fresult2errno(res);
+	return 0;
+}
+
+#define S_IREAD S_IRUSR
+#define S_IWRITE S_IWUSR
+
+int shell_mkdir(const char *path, mode_t mode)
 {
 	FRESULT res;
 
 	if ((res = f_mkdir(path)) != FR_OK)
-		return -1;
+		return fresult2errno(res);
 
 	BYTE attr = 0;
@@ -397,13 +504,13 @@
 
 	if((res = f_chmod(path, attr, mask)) != FR_OK) {
-		return -1;
-	}
-
-	return 0;
-}
-
-int chmod(const char *path, mode_t mode)
-{
-	FRESULT ret;
+		return fresult2errno(res);
+	}
+
+	return 0;
+}
+
+int shell_chmod(const char *path, mode_t mode)
+{
+	FRESULT res;
 	BYTE attr = 0;
 	BYTE mask = AM_RDO | AM_SYS; // AM_ARC, AM_HID
@@ -418,12 +525,12 @@
 	}
 
-	if((ret = f_chmod(path, attr, mask)) != FR_OK) {
-		return -1;
-	}
-
-	return 0;
-}
-
-char *getcwd(char *buf, size_t size)
+	if((res = f_chmod(path, attr, mask)) != FR_OK) {
+		return fresult2errno(res);
+	}
+
+	return 0;
+}
+
+char *shell_getcwd(char *buf, size_t size)
 {
 	FRESULT ret;
@@ -435,48 +542,39 @@
 }
 
-int chdir(const char *path)
-{
-	FRESULT ret;
-	if ((ret = f_chdir(path)) != FR_OK) {
-		return -1;
-	}
-
-	return 0;
-}
-
-int chroot(const char *path)
-{
-	abort();
-	return -1;
-}
-
-DIR *opendir(const char *path)
-{
-	DIR *dir = malloc(sizeof(DIR) + sizeof(struct dirent));
-	FRESULT ret;
-	if ((ret = f_opendir(dir, path)) != FR_OK) {
-		free(dir);
-		return NULL;
-	}
-
-	dir->dirent = &dir[1];
-	return dir;
-}
-
-int closedir(DIR *dir)
-{
-	FRESULT ret;
-	if ((ret = f_closedir(dir)) != FR_OK) {
-		free(dir);
-		return -1;
-	}
-
-	free(dir);
-	return 0;
-}
-
-struct dirent *readdir(DIR *dir)
-{
-	struct dirent *de = dir->dirent;
+int shell_chdir(const char *path)
+{
+	FRESULT res;
+	if ((res = f_chdir(path)) != FR_OK) {
+		return fresult2errno(res);
+	}
+
+	return 0;
+}
+
+int shell_chroot(const char *path)
+{
+	shell_abort();
+	return -EPERM;
+}
+
+int dir_close(struct _IO_FILE *fp)
+{
+	FRESULT res;
+	if ((res = f_closedir(&fp->dir)) != FR_OK) {
+		return fresult2errno(res);
+	}
+
+	return 0;
+}
+
+int shell_getdents(int fd, struct dirent *de, size_t len)
+{
+	if (len < sizeof(struct dirent))
+		return -EINVAL;
+
+	struct _IO_FILE *fp = fd_to_fp(fd);
+	if (fp == NULL)
+		return -EBADF;
+
 	FILINFO fno;
 #if _USE_LFN
@@ -485,40 +583,117 @@
 	fno.lfsize = sizeof lfn;
 #endif
-	FRESULT ret;
-	if ((ret = f_readdir(dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
-		return NULL;
+	FRESULT res;
+	if ((res = f_readdir(&fp->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
+		return fresult2errno(res);
 	}
 
 	memset(de, 0, sizeof(*de));
 #if _USE_LFN
-	strlcpy(de->d_name, *fno.lfname ? fno.lfname : fno.fname, sizeof(de->d_name));
+	ntlibc_strlcpy(de->d_name, *fno.lfname ? fno.lfname : fno.fname, sizeof(de->d_name));
 #else
-	strlcpy(de->d_name, fno.fname, sizeof(de->d_name));
+	ntlibc_strlcpy(de->d_name, fno.fname, sizeof(de->d_name));
 #endif
 
-	return de;
-}
-
-void rewinddir(DIR *dir)
-{
-	FRESULT ret;
-	if ((ret = f_rewinddir(dir)) != FR_OK) {
-		return;
-	}
-}
-
-void seekdir(DIR *dir, long pos)
-{
-	abort();
-}
-
-long telldir(DIR *dir)
-{
-	abort();
-	return 0;
-}
-
-int shell_getpid(int n)
+	return 0;
+}
+
+size_t dir_read(struct _IO_FILE *fp, unsigned char *data, size_t len)
+{
+	return -EPERM;
+}
+
+size_t dir_write(struct _IO_FILE *fp, const unsigned char *data, size_t len)
+{
+	return -EPERM;
+}
+
+off_t dir_seek(struct _IO_FILE *fp, off_t ptr, int dir)
+{
+	FRESULT res;
+
+	if (dir != SEEK_SET)
+		return -EINVAL;
+
+	if (ptr == 0) {
+		if ((res = f_rewinddir(&fp->dir)) != FR_OK) {
+			return fresult2errno(res);
+		}
+	}
+	else {
+		FILINFO fno;
+#if _USE_LFN
+		static char lfn[_MAX_LFN + 1];   /* Buffer to store the LFN */
+		fno.lfname = lfn;
+		fno.lfsize = sizeof lfn;
+#endif
+		if ((res = f_rewinddir(&fp->dir)) != FR_OK) {
+			return fresult2errno(res);
+		}
+
+		for (int i = 0; i < ptr; i++) {
+			if ((res = f_readdir(&fp->dir, &fno)) != FR_OK || fno.fname[0] == '\0') {
+				return fresult2errno(res);
+			}
+		}
+	}
+
+	return ptr;
+}
+
+int dir_ioctl(struct _IO_FILE *fp, int req, void *arg)
+{
+	return -EINVAL;
+}
+
+pid_t shell_getpid(void)
 {
 	return 1;
 }
+
+int shell_access(const char *path, int mode)
+{
+	struct stat st;
+	int ret;
+
+	ret = shell_stat(path, &st);
+	if (ret != 0)
+		return ret;
+
+	return 0;
+}
+
+//#include "../musl-1.1.18/include/bits/limits.h"
+#define PAGE_SIZE 4096
+
+uint32_t  __CmdBase;
+uint32_t  __CmdLimit;
+
+void *shell_brk(void *addr)
+{
+	if (addr == 0) {
+		return (void *)((intptr_t)&__CmdBase + 0x20000);
+	}
+	if ((addr >= (intptr_t)&__CmdBase + 0x20000) && (addr < &__CmdLimit)) {
+		return addr;
+	}
+	return (void *)-1;
+}
+
+void *shell_mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoffset)
+{
+	if (fd != -1)
+		return -EINVAL;
+
+	if ((length >= 0) && (length <= (intptr_t)&__CmdLimit - (intptr_t)&__CmdBase - 0x20000)) {
+		return &__CmdBase + 0x20000;
+	}
+	return (void *)-1;
+}
+
+int shell_mprotect(void *addr, size_t len, int prot)
+{
+	//if ((addr >= (intptr_t)&__CmdBase + 0x20000) && ((intptr_t)addr + len < &__CmdLimit)) {
+		return 0;
+	//}
+	//return -1;
+}
