diff --git a/reactos/lib/msvcrt/io/dup.c b/reactos/lib/msvcrt/io/dup.c index 93647914e4f..d677901567f 100644 --- a/reactos/lib/msvcrt/io/dup.c +++ b/reactos/lib/msvcrt/io/dup.c @@ -1,8 +1,33 @@ +/* $Id: dup.c,v 1.2 2002/05/07 22:31:25 hbirr Exp $ */ +#include #include #include int _dup(int handle) { - return __fileno_alloc(_get_osfhandle(handle), __fileno_getmode(handle)); + HANDLE hFile; + HANDLE hProcess = GetCurrentProcess(); + BOOL result; + int fd; + + hFile = _get_osfhandle(handle); + if (hFile == INVALID_HANDLE_VALUE) + return -1; + result = DuplicateHandle(hProcess, + hFile, + hProcess, + &hFile, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if (result == FALSE) + return -1; + + fd = __fileno_alloc(hFile, __fileno_getmode(handle)); + if (fd < 0) + { + CloseHandle(hFile); + } + return fd; } diff --git a/reactos/lib/msvcrt/io/open.c b/reactos/lib/msvcrt/io/open.c index 949ff1e688a..b7dd8a2bc09 100644 --- a/reactos/lib/msvcrt/io/open.c +++ b/reactos/lib/msvcrt/io/open.c @@ -1,4 +1,5 @@ -/* +/* $Id: open.c,v 1.8 2002/05/07 22:31:25 hbirr Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/crtdll/io/open.c @@ -28,6 +29,9 @@ #define NDEBUG #include +#define STD_AUX_HANDLE 3 +#define STD_PRINTER_HANDLE 4 + typedef struct _fileno_modes_type { HANDLE hFile; @@ -37,8 +41,7 @@ typedef struct _fileno_modes_type fileno_modes_type *fileno_modes = NULL; -int maxfno = 5; -int minfno = 5; +int maxfno = 0; char __is_text_file(FILE *p) { @@ -60,6 +63,7 @@ int _open(const char *_path, int _oflag,...) DWORD dwCreationDistribution = 0; DWORD dwFlagsAndAttributes = 0; DWORD dwLastError; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; #if !defined(NDEBUG) && defined(DBG) va_start(arg, _oflag); @@ -126,11 +130,14 @@ int _open(const char *_path, int _oflag,...) dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n"); } + + if (_oflag & _O_NOINHERIT) + sa.bInheritHandle = FALSE; hFile = CreateFileA(_path, dwDesiredAccess, dwShareMode, - NULL, + &sa, dwCreationDistribution, dwFlagsAndAttributes, NULL); @@ -150,6 +157,10 @@ int _open(const char *_path, int _oflag,...) return -1; } DPRINT("OK\n"); + if (!(_oflag & (_O_TEXT|_O_BINARY))) + { + _oflag |= _fmode; + } return __fileno_alloc(hFile,_oflag); } @@ -165,6 +176,7 @@ int _wopen(const wchar_t *_path, int _oflag,...) DWORD dwShareMode = 0; DWORD dwCreationDistribution = 0; DWORD dwFlagsAndAttributes = 0; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; #if !defined(NDEBUG) && defined(DBG) va_start(arg, _oflag); @@ -230,10 +242,13 @@ int _wopen(const wchar_t *_path, int _oflag,...) if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED ) dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + if (_oflag & _O_NOINHERIT) + sa.bInheritHandle = FALSE; + hFile = CreateFileW(_path, dwDesiredAccess, dwShareMode, - NULL, + &sa, dwCreationDistribution, dwFlagsAndAttributes, NULL); @@ -251,7 +266,7 @@ __fileno_alloc(HANDLE hFile, int mode) if (hFile < 0) return -1; - for(i=minfno;i= maxfno || fileno_modes[fileno].fd == -1) { - case 0: - return GetStdHandle(STD_INPUT_HANDLE); - case 1: - return GetStdHandle(STD_OUTPUT_HANDLE); - case 2: - return GetStdHandle(STD_ERROR_HANDLE); - case 3: - return GetStdHandle(STD_AUX_HANDLE); - case 4: - return GetStdHandle(STD_PRINTER_HANDLE); - default: - break; + return (void *)-1; } - - if ( fileno >= maxfno ) - return (void *)-1; - - if ( fileno_modes[fileno].fd == -1 ) - return (void *)-1; return fileno_modes[fileno].hFile; } int __fileno_dup2( int handle1, int handle2 ) { - if ( handle1 >= maxfno ) - return -1; - - if ( handle1 < 0 ) - return -1; - if ( handle2 >= maxfno ) - return -1; - - if ( handle2 < 0 ) - return -1; - - memcpy(&fileno_modes[handle1],&fileno_modes[handle2],sizeof(fileno_modes)); - - return handle1; + HANDLE hProcess; + BOOL result; + if (handle1 >= maxfno || handle1 < 0 || handle2 >= maxfno || handle2 < 0 ) + { + __set_errno(EBADF); + return -1; + } + if (fileno_modes[handle1].fd == -1) + { + __set_errno(EBADF); + return -1; + } + if (handle1 == handle2) + return handle1; + if (fileno_modes[handle2].fd != -1) + { + _close(handle2); + } + hProcess = GetCurrentProcess(); + result = DuplicateHandle(hProcess, + fileno_modes[handle1].hFile, + hProcess, + &fileno_modes[handle2].hFile, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if (result) + { + fileno_modes[handle2].fd = handle2; + fileno_modes[handle2].mode = fileno_modes[handle1].mode; + switch (handle2) + { + case 0: + SetStdHandle(STD_INPUT_HANDLE, fileno_modes[handle2].hFile); + break; + case 1: + SetStdHandle(STD_OUTPUT_HANDLE, fileno_modes[handle2].hFile); + break; + case 2: + SetStdHandle(STD_ERROR_HANDLE, fileno_modes[handle2].hFile); + break; + case 3: + SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile); + break; + case 4: + SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile); + break; + } + return handle1; + } + else + { + __set_errno(EMFILE); // Is this the correct error no.? + return -1; + } } int __fileno_setmode(int _fd, int _newmode) { int m; - if ( _fd < minfno ) - return -1; - - if ( _fd >= maxfno ) + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); return -1; + } m = fileno_modes[_fd].mode; fileno_modes[_fd].mode = _newmode; @@ -348,24 +382,22 @@ int __fileno_setmode(int _fd, int _newmode) int __fileno_getmode(int _fd) { - if ( _fd < minfno ) + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); return -1; - - if ( _fd >= maxfno ) - return -1; - + } return fileno_modes[_fd].mode; } - int __fileno_close(int _fd) { - if ( _fd < 0 ) - return -1; - - if ( _fd >= maxfno ) + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); return -1; + } fileno_modes[_fd].fd = -1; fileno_modes[_fd].hFile = (HANDLE)-1; @@ -381,3 +413,78 @@ void *_get_osfhandle( int fileno ) { return filehnd(fileno); } + +void __fileno_init(void) +{ + ULONG count = 0, i; + HANDLE *pFile; + char* pmode; + STARTUPINFO StInfo; + + GetStartupInfoA(&StInfo); + + if (StInfo.lpReserved2 && StInfo.cbReserved2 >= sizeof(ULONG)) + { + count = *(ULONG*)StInfo.lpReserved2; +/* + if (sizeof(ULONG) + count * (sizeof(HANDLE) + sizeof(char)) != StInfo.cbReserved2) + { + count = 0; + } +*/ + } + maxfno = 255; + while(count >= maxfno) + maxfno += 255; + + fileno_modes = (fileno_modes_type*)malloc(sizeof(fileno_modes_type) * maxfno); + memset(fileno_modes, -1, sizeof(fileno_modes_type) * maxfno); + + if (count) + { + pFile = (HANDLE*)(StInfo.lpReserved2 + sizeof(ULONG) + count * sizeof(char)); + pmode = (char*)(StInfo.lpReserved2 + sizeof(ULONG)); + for (i = 0; i < count; i++) + { + if (*pFile != INVALID_HANDLE_VALUE) + { + fileno_modes[i].fd = i; + fileno_modes[i].mode = ((*pmode << 8) & (_O_TEXT|_O_BINARY)) | (*pmode & _O_ACCMODE); + fileno_modes[i].hFile = *pFile; + } + pFile++; + pmode++; + } + } + + if (fileno_modes[0].fd == -1) + { + fileno_modes[0].fd = 0; + fileno_modes[0].hFile = GetStdHandle(STD_INPUT_HANDLE); + fileno_modes[0].mode = _O_RDONLY|_O_TEXT; + } + if (fileno_modes[1].fd == -1) + { + fileno_modes[1].fd = 1; + fileno_modes[1].hFile = GetStdHandle(STD_OUTPUT_HANDLE); + fileno_modes[1].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[2].fd == -1) + { + fileno_modes[2].fd = 2; + fileno_modes[2].hFile = GetStdHandle(STD_ERROR_HANDLE); + fileno_modes[2].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[3].fd == -1) + { + fileno_modes[3].fd = 3; + fileno_modes[3].hFile = GetStdHandle(STD_AUX_HANDLE); + fileno_modes[3].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[4].fd == -1) + { + fileno_modes[4].fd = 4; + fileno_modes[4].hFile = GetStdHandle(STD_PRINTER_HANDLE); + fileno_modes[4].mode = _O_WRONLY|_O_TEXT; + } +} diff --git a/reactos/lib/msvcrt/io/pipe.c b/reactos/lib/msvcrt/io/pipe.c index 531ee22a9b7..a99130f3cb4 100644 --- a/reactos/lib/msvcrt/io/pipe.c +++ b/reactos/lib/msvcrt/io/pipe.c @@ -1,4 +1,5 @@ -/* +/* $Id: pipe.c,v 1.2 2002/05/07 22:31:25 hbirr Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/crtdll/io/pipe.c @@ -9,18 +10,36 @@ */ #include #include +#include #include int _pipe(int _fildes[2], unsigned int size, int mode ) { HANDLE hReadPipe, hWritePipe; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - if (!CreatePipe(&hReadPipe,&hWritePipe,NULL,size)) + if (mode & O_NOINHERIT) + sa.bInheritHandle = FALSE; + + if (!CreatePipe(&hReadPipe,&hWritePipe,&sa,size)) return -1; - _fildes[0] = __fileno_alloc(hReadPipe, mode); - _fildes[1] = __fileno_alloc(hWritePipe, mode); + if ((_fildes[0] = __fileno_alloc(hReadPipe, mode)) < 0) + { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + __set_errno(EMFILE); + return -1; + } + if ((_fildes[1] = __fileno_alloc(hWritePipe, mode)) < 0) + { + __fileno_close(_fildes[0]); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + __set_errno(EMFILE); + return -1; + } return 0; } diff --git a/reactos/lib/msvcrt/io/setmode.c b/reactos/lib/msvcrt/io/setmode.c index 38be0cd5625..7245f10d8ad 100644 --- a/reactos/lib/msvcrt/io/setmode.c +++ b/reactos/lib/msvcrt/io/setmode.c @@ -1,4 +1,5 @@ -/* +/* $Id: setmode.c,v 1.4 2002/05/07 22:31:25 hbirr Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/crtdll/io/setmode.c @@ -19,7 +20,5 @@ int _setmode(int _fd, int _newmode) { DPRINT("_setmod(fd %d, newmode %x)\n", _fd, _newmode); - if (_fd >= 0 && _fd < 5) - return _O_TEXT; return __fileno_setmode(_fd, _newmode); } diff --git a/reactos/lib/msvcrt/misc/dllmain.c b/reactos/lib/msvcrt/misc/dllmain.c index 870f5368213..76d05552a0f 100644 --- a/reactos/lib/msvcrt/misc/dllmain.c +++ b/reactos/lib/msvcrt/misc/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.13 2002/05/05 14:57:41 chorns Exp $ +/* $Id: dllmain.c,v 1.14 2002/05/07 22:31:25 hbirr Exp $ * * ReactOS MSVCRT.DLL Compatibility Library */ @@ -99,6 +99,10 @@ DllMain(PVOID hinstDll, return FALSE; } } + if (nAttachCount==0) + { + __fileno_init(); + } /* create tls stuff */ if (!CreateThreadData()) @@ -113,6 +117,7 @@ DllMain(PVOID hinstDll, /* FIXME: more initializations... */ nAttachCount++; + DPRINT("Attach done\n"); break; case DLL_THREAD_ATTACH://2 @@ -149,6 +154,7 @@ DllMain(PVOID hinstDll, hHeap = NULL; #endif } + DPRINT("Detach done\n"); } break; } diff --git a/reactos/lib/msvcrt/process/spawnve.c b/reactos/lib/msvcrt/process/spawnve.c index ef57d96092d..8de4ff1e5c0 100644 --- a/reactos/lib/msvcrt/process/spawnve.c +++ b/reactos/lib/msvcrt/process/spawnve.c @@ -1,3 +1,4 @@ +/* $Id: spawnve.c,v 1.3 2002/05/07 22:31:26 hbirr Exp $ */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ @@ -12,6 +13,7 @@ #include #include #include +#include #define NDEBUG #include @@ -36,36 +38,93 @@ // information about crtdll file handles is not passed to child int _fileinfo_dll = 0; +extern int maxfno; + static int -direct_exec_tail(const char *program, const char *args, - const char * envp, - PROCESS_INFORMATION *ProcessInformation) +direct_exec_tail(int mode, const char *program, + const char *args, const char * envp) { - static STARTUPINFO StartupInfo; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + char* fmode; + HANDLE* hFile; + int i, last; + BOOL bResult; + DPRINT("direct_exec_tail()\n"); + + memset (&StartupInfo, 0, sizeof(STARTUPINFO)); StartupInfo.cb = sizeof(STARTUPINFO); - StartupInfo.lpReserved= NULL; - StartupInfo.dwFlags = 0 /*STARTF_USESTDHANDLES*/; - StartupInfo.wShowWindow = SW_SHOWDEFAULT; - StartupInfo.lpReserved2 = NULL; - StartupInfo.cbReserved2 = 0; - StartupInfo.hStdInput = _get_osfhandle(0); - StartupInfo.hStdOutput = _get_osfhandle(1); - StartupInfo.hStdError = _get_osfhandle(2); - - if (! CreateProcessA((char *)program,(char *)args,NULL,NULL,TRUE,0,(LPVOID)envp,NULL,&StartupInfo,ProcessInformation) ) + for (last = i = 0; i < maxfno; i++) { + if ((void*)-1 != _get_osfhandle(i)) + { + last = i + 1; + } + } + + if (last) + { + StartupInfo.cbReserved2 = sizeof(ULONG) + last * (sizeof(char) + sizeof(HANDLE)); + StartupInfo.lpReserved2 = malloc(StartupInfo.cbReserved2); + if (StartupInfo.lpReserved2 == NULL) + { + return -1; + } + + *(DWORD*)StartupInfo.lpReserved2 = last; + fmode = (char*)(StartupInfo.lpReserved2 + sizeof(ULONG)); + hFile = (HANDLE*)(StartupInfo.lpReserved2 + sizeof(ULONG) + last * sizeof(char)); + for (i = 0; i < last; i++) + { + int mode = __fileno_getmode(i); + HANDLE h = _get_osfhandle(i); + /* FIXME: The test of console handles (((ULONG)Handle) & 0x10000003) == 0x3) + * is possible wrong + */ + if ((((ULONG)h) & 0x10000003) == 0x3 || mode & _O_NOINHERIT) + { + *hFile = INVALID_HANDLE_VALUE; + } + else + { + *hFile = h; + *fmode = (_O_ACCMODE & mode) | (((_O_TEXT | _O_BINARY) & mode) >> 8); + } + fmode++; + hFile++; + } + } + + bResult = CreateProcessA((char *)program, + (char *)args, + NULL, + NULL, + TRUE, + mode == _P_DETACH ? DETACHED_PROCESS : 0, + (LPVOID)envp, + NULL, + &StartupInfo, + &ProcessInformation); + Sleep(100); + if (StartupInfo.lpReserved2) + { + free(StartupInfo.lpReserved2); + } + + if (!bResult) + { + DPRINT("%x\n", GetLastError()); __set_errno( GetLastError() ); return -1; } - - return (int)ProcessInformation->hProcess; + CloseHandle(ProcessInformation.hThread); + return (int)ProcessInformation.hProcess; } -static int vdm_exec(const char *program, char **argv, char **envp, - PROCESS_INFORMATION *ProcessInformation) +static int vdm_exec(int mode, const char *program, char **argv, char *envp) { static char args[1024]; int i = 0; @@ -78,11 +137,10 @@ static int vdm_exec(const char *program, char **argv, char **envp, i++; } - return direct_exec_tail(program,args,envp,ProcessInformation); + return direct_exec_tail(mode,program,args,envp); } -static int go32_exec(const char *program, char **argv, char **envp, - PROCESS_INFORMATION *ProcessInformation) +static int go32_exec(int mode, const char *program, char **argv, char **envp) { char * penvblock, * ptr; char * args; @@ -118,16 +176,16 @@ static int go32_exec(const char *program, char **argv, char **envp, strcat(args," "); } } - - result = direct_exec_tail(program,args,(const char*)penvblock,ProcessInformation); + + DPRINT("'%s'\n", args); + result = direct_exec_tail(mode, program,args,(const char*)penvblock); free(args); free(penvblock); return result; } int -command_exec(const char *program, char **argv, char **envp, - PROCESS_INFORMATION *ProcessInformation) +command_exec(int mode, const char *program, char **argv, char *envp) { static char args[1024]; int i = 0; @@ -143,12 +201,11 @@ command_exec(const char *program, char **argv, char **envp, i++; } - return direct_exec_tail(program,args,envp,ProcessInformation); + return direct_exec_tail(mode,program,args,envp); } -static int script_exec(const char *program, char **argv, char **envp, - PROCESS_INFORMATION *ProcessInformation) +static int script_exec(int mode, const char *program, char **argv, char **envp) { return 0; } @@ -160,8 +217,7 @@ static int script_exec(const char *program, char **argv, char **envp, executable from one of the shells used on MSDOS. */ static struct { const char *extension; - int (*interp)(const char *, char **, char **, - PROCESS_INFORMATION *); + int (*interp)(int , const char*, char **, char **); } interpreters[] = { { ".com", vdm_exec }, { ".exe", go32_exec }, @@ -190,7 +246,6 @@ static struct { int _spawnve(int mode, const char *path, char *const argv[], char *const envp[]) { /* This is the one that does the work! */ - PROCESS_INFORMATION ProcessInformation; union { char *const *x; char **p; } u; int i = -1; char **argvp; @@ -201,7 +256,7 @@ int _spawnve(int mode, const char *path, char *const argv[], char *const envp[]) int found = 0; DWORD ExitCode; - DPRINT("_spawnve('%s')\n", path); + DPRINT("_spawnve(mode %x, '%s')\n", mode, path); if (path == 0 || argv[0] == 0) { @@ -275,20 +330,22 @@ int _spawnve(int mode, const char *path, char *const argv[], char *const envp[]) return -1; } errno = e; - i = interpreters[i].interp(rpath, argvp, envpp, &ProcessInformation); + i = interpreters[i].interp(mode, rpath, argvp, envpp); + if (i < 0) + { + return -1; + } if (mode == P_OVERLAY) + { + CloseHandle((HANDLE)i); exit(i); + } if (mode == P_WAIT) { - WaitForSingleObject(ProcessInformation.hProcess,INFINITE); - GetExitCodeProcess(ProcessInformation.hProcess,&ExitCode); + WaitForSingleObject((HANDLE)i, INFINITE); + GetExitCodeProcess((HANDLE)i, &ExitCode); + CloseHandle((HANDLE)i); i = (int)ExitCode; - CloseHandle(ProcessInformation.hThread); - CloseHandle(ProcessInformation.hProcess); - } - else - { - CloseHandle(ProcessInformation.hThread); } return i; } diff --git a/reactos/lib/msvcrt/sys_stat/fstat.c b/reactos/lib/msvcrt/sys_stat/fstat.c index 71e6023e87a..e8c2c0baffe 100644 --- a/reactos/lib/msvcrt/sys_stat/fstat.c +++ b/reactos/lib/msvcrt/sys_stat/fstat.c @@ -1,7 +1,8 @@ -/* +/* $Id: fstat.c,v 1.9 2002/05/07 22:31:26 hbirr Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/sys/fstat.c + * FILE: lib/msvcrt/sys/fstat.c * PURPOSE: Gather file information * PROGRAMER: Boudewijn Dekker * UPDATE HISTORY: @@ -18,69 +19,124 @@ int _fstat(int fd, struct stat *statbuf) { BY_HANDLE_FILE_INFORMATION FileInformation; + DWORD dwFileType; + void* handle; if (!statbuf) - { - __set_errno(EINVAL); - return -1; - } - - if (fd >= 0 && fd <= 4) { - memset(statbuf, 0, sizeof(struct stat)); - statbuf->st_dev = fd; - statbuf->st_mode = S_IFCHR; - return 0; + __set_errno(EINVAL); + return -1; } - if (!GetFileInformationByHandle(_get_osfhandle(fd),&FileInformation)) + if ((void*)-1 == (handle = _get_osfhandle(fd))) + { + __set_errno(EBADF); + return -1; + } + + memset (statbuf, 0, sizeof(struct stat)); + + dwFileType = GetFileType(handle); + + if (dwFileType == FILE_TYPE_DISK) + { + if (!GetFileInformationByHandle(handle,&FileInformation)) { __set_errno(EBADF); return -1; } - statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); - statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); - statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); + statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); - statbuf->st_dev = fd; - statbuf->st_size = FileInformation.nFileSizeLow; - statbuf->st_mode = S_IREAD; - if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - statbuf->st_mode |= S_IFDIR; + statbuf->st_dev = fd; + statbuf->st_size = FileInformation.nFileSizeLow; + statbuf->st_mode = S_IREAD; + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR; + else + statbuf->st_mode |= S_IFREG; + if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + } + else if (dwFileType == FILE_TYPE_CHAR) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFCHR; + } + else if (dwFileType == FILE_TYPE_PIPE) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFIFO; + } else - statbuf->st_mode |= S_IFREG; - if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + { + // dwFileType is FILE_TYPE_UNKNOWN or has a bad value + __set_errno(EBADF); + return -1; + } return 0; } __int64 _fstati64 (int fd, struct _stati64* statbuf) { BY_HANDLE_FILE_INFORMATION FileInformation; + DWORD dwFileType; + void *handle; if (!statbuf) - { - __set_errno(EINVAL); - return -1; - } + { + __set_errno(EINVAL); + return -1; + } - if (!GetFileInformationByHandle(_get_osfhandle(fd), - &FileInformation)) - { - __set_errno(EBADF); - return -1; - } - statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); - statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); - statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); + if ((void*)-1 == (handle = _get_osfhandle(fd))) + { + __set_errno(EBADF); + return -1; + } + + memset(statbuf, 0, sizeof(struct _stati64)); - statbuf->st_dev = fd; - statbuf->st_size = (((__int64)FileInformation.nFileSizeHigh) << 32) + + dwFileType = GetFileType(handle); + + if (dwFileType == FILE_TYPE_DISK) + { + if (!GetFileInformationByHandle(handle,&FileInformation)) + { + __set_errno(EBADF); + return -1; + } + statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); + + statbuf->st_dev = fd; + statbuf->st_size = (((__int64)FileInformation.nFileSizeHigh) << 32) + FileInformation.nFileSizeLow; - statbuf->st_mode = S_IREAD; - if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - statbuf->st_mode |= S_IFDIR; + statbuf->st_mode = S_IREAD; + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR; + else + statbuf->st_mode |= S_IFREG; + if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + } + else if (dwFileType == FILE_TYPE_CHAR) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFCHR; + } + else if (dwFileType == FILE_TYPE_PIPE) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFIFO; + } else - statbuf->st_mode |= S_IFREG; - if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + { + // dwFileType is FILE_TYPE_UNKNOWN or has a bad value + __set_errno(EBADF); + return -1; + } return 0; } + +