1*c2c66affSColin Finck #include <precomp.h> 2*c2c66affSColin Finck #include <tchar.h> 3*c2c66affSColin Finck #include <direct.h> 4*c2c66affSColin Finck 5*c2c66affSColin Finck HANDLE fdtoh(int fd); 6*c2c66affSColin Finck 7*c2c66affSColin Finck #define ALL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)) 8*c2c66affSColin Finck #define ALL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) 9*c2c66affSColin Finck #define ALL_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)) 10*c2c66affSColin Finck 11*c2c66affSColin Finck #ifdef UNICODE 12*c2c66affSColin Finck #define TCHAR4 ULONGLONG 13*c2c66affSColin Finck #else 14*c2c66affSColin Finck #define TCHAR4 ULONG 15*c2c66affSColin Finck #endif 16*c2c66affSColin Finck 17*c2c66affSColin Finck #define TCSIZE sizeof(_TCHAR) 18*c2c66affSColin Finck #define TOULL(x) ((TCHAR4)(x)) 19*c2c66affSColin Finck 20*c2c66affSColin Finck #define EXE ((TOULL('e')<<(2*TCSIZE)) | (TOULL('x')<<TCSIZE) | (TOULL('e'))) 21*c2c66affSColin Finck #define BAT ((TOULL('b')<<(2*TCSIZE)) | (TOULL('a')<<TCSIZE) | (TOULL('t'))) 22*c2c66affSColin Finck #define CMD ((TOULL('c')<<(2*TCSIZE)) | (TOULL('m')<<TCSIZE) | (TOULL('d'))) 23*c2c66affSColin Finck #define COM ((TOULL('c')<<(2*TCSIZE)) | (TOULL('o')<<TCSIZE) | (TOULL('m'))) 24*c2c66affSColin Finck 25*c2c66affSColin Finck int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf) 26*c2c66affSColin Finck { 27*c2c66affSColin Finck DWORD dw; 28*c2c66affSColin Finck WIN32_FILE_ATTRIBUTE_DATA hfi; 29*c2c66affSColin Finck unsigned short mode = ALL_S_IREAD; 30*c2c66affSColin Finck int plen; 31*c2c66affSColin Finck 32*c2c66affSColin Finck TRACE(":file (%s) buf(%p)\n",path,buf); 33*c2c66affSColin Finck 34*c2c66affSColin Finck plen = _tcslen(path); 35*c2c66affSColin Finck while (plen && path[plen-1]==' ') 36*c2c66affSColin Finck plen--; 37*c2c66affSColin Finck 38*c2c66affSColin Finck if (plen && (plen<2 || path[plen-2]!=':') && 39*c2c66affSColin Finck (path[plen-1]==':' || path[plen-1]=='\\' || path[plen-1]=='/')) 40*c2c66affSColin Finck { 41*c2c66affSColin Finck *_errno() = ENOENT; 42*c2c66affSColin Finck return -1; 43*c2c66affSColin Finck } 44*c2c66affSColin Finck 45*c2c66affSColin Finck if (!GetFileAttributesEx(path, GetFileExInfoStandard, &hfi)) 46*c2c66affSColin Finck { 47*c2c66affSColin Finck TRACE("failed (%d)\n",GetLastError()); 48*c2c66affSColin Finck *_errno() = ENOENT; 49*c2c66affSColin Finck return -1; 50*c2c66affSColin Finck } 51*c2c66affSColin Finck 52*c2c66affSColin Finck memset(buf,0,sizeof(struct __stat64)); 53*c2c66affSColin Finck 54*c2c66affSColin Finck /* FIXME: rdev isn't drive num, despite what the docs say-what is it? 55*c2c66affSColin Finck Bon 011120: This FIXME seems incorrect 56*c2c66affSColin Finck Also a letter as first char isn't enough to be classified 57*c2c66affSColin Finck as a drive letter 58*c2c66affSColin Finck */ 59*c2c66affSColin Finck if (isalpha(*path)&& (*(path+1)==':')) 60*c2c66affSColin Finck buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */ 61*c2c66affSColin Finck else 62*c2c66affSColin Finck buf->st_dev = buf->st_rdev = _getdrive() - 1; 63*c2c66affSColin Finck 64*c2c66affSColin Finck /* Dir, or regular file? */ 65*c2c66affSColin Finck if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 66*c2c66affSColin Finck mode |= (_S_IFDIR | ALL_S_IEXEC); 67*c2c66affSColin Finck else 68*c2c66affSColin Finck { 69*c2c66affSColin Finck mode |= _S_IFREG; 70*c2c66affSColin Finck /* executable? */ 71*c2c66affSColin Finck if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */ 72*c2c66affSColin Finck { 73*c2c66affSColin Finck unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) | 74*c2c66affSColin Finck (tolower(path[plen-3]) << 16); 75*c2c66affSColin Finck if (ext == EXE || ext == BAT || ext == CMD || ext == COM) 76*c2c66affSColin Finck mode |= ALL_S_IEXEC; 77*c2c66affSColin Finck } 78*c2c66affSColin Finck } 79*c2c66affSColin Finck 80*c2c66affSColin Finck if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 81*c2c66affSColin Finck mode |= ALL_S_IWRITE; 82*c2c66affSColin Finck 83*c2c66affSColin Finck buf->st_mode = mode; 84*c2c66affSColin Finck buf->st_nlink = 1; 85*c2c66affSColin Finck buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; 86*c2c66affSColin Finck RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw); 87*c2c66affSColin Finck buf->st_atime = dw; 88*c2c66affSColin Finck RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); 89*c2c66affSColin Finck buf->st_mtime = buf->st_ctime = dw; 90*c2c66affSColin Finck TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink, 91*c2c66affSColin Finck (int)(buf->st_size >> 32),(int)buf->st_size, 92*c2c66affSColin Finck (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime); 93*c2c66affSColin Finck return 0; 94*c2c66affSColin Finck } 95*c2c66affSColin Finck 96*c2c66affSColin Finck #ifndef _UNICODE 97*c2c66affSColin Finck 98*c2c66affSColin Finck int CDECL _fstat64(int fd, struct __stat64* buf) 99*c2c66affSColin Finck { 100*c2c66affSColin Finck DWORD dw; 101*c2c66affSColin Finck DWORD type; 102*c2c66affSColin Finck BY_HANDLE_FILE_INFORMATION hfi; 103*c2c66affSColin Finck HANDLE hand = fdtoh(fd); 104*c2c66affSColin Finck 105*c2c66affSColin Finck TRACE(":fd (%d) stat (%p)\n",fd,buf); 106*c2c66affSColin Finck if (hand == INVALID_HANDLE_VALUE) 107*c2c66affSColin Finck return -1; 108*c2c66affSColin Finck 109*c2c66affSColin Finck if (!buf) 110*c2c66affSColin Finck { 111*c2c66affSColin Finck WARN(":failed-NULL buf\n"); 112*c2c66affSColin Finck _dosmaperr(ERROR_INVALID_PARAMETER); 113*c2c66affSColin Finck return -1; 114*c2c66affSColin Finck } 115*c2c66affSColin Finck 116*c2c66affSColin Finck memset(&hfi, 0, sizeof(hfi)); 117*c2c66affSColin Finck memset(buf, 0, sizeof(struct __stat64)); 118*c2c66affSColin Finck type = GetFileType(hand); 119*c2c66affSColin Finck if (type == FILE_TYPE_PIPE) 120*c2c66affSColin Finck { 121*c2c66affSColin Finck buf->st_dev = buf->st_rdev = fd; 122*c2c66affSColin Finck buf->st_mode = _S_IFIFO; 123*c2c66affSColin Finck buf->st_nlink = 1; 124*c2c66affSColin Finck } 125*c2c66affSColin Finck else if (type == FILE_TYPE_CHAR) 126*c2c66affSColin Finck { 127*c2c66affSColin Finck buf->st_dev = buf->st_rdev = fd; 128*c2c66affSColin Finck buf->st_mode = _S_IFCHR; 129*c2c66affSColin Finck buf->st_nlink = 1; 130*c2c66affSColin Finck } 131*c2c66affSColin Finck else /* FILE_TYPE_DISK etc. */ 132*c2c66affSColin Finck { 133*c2c66affSColin Finck if (!GetFileInformationByHandle(hand, &hfi)) 134*c2c66affSColin Finck { 135*c2c66affSColin Finck WARN(":failed-last error (%d)\n",GetLastError()); 136*c2c66affSColin Finck _dosmaperr(ERROR_INVALID_PARAMETER); 137*c2c66affSColin Finck return -1; 138*c2c66affSColin Finck } 139*c2c66affSColin Finck buf->st_mode = _S_IFREG | ALL_S_IREAD; 140*c2c66affSColin Finck if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 141*c2c66affSColin Finck buf->st_mode |= ALL_S_IWRITE; 142*c2c66affSColin Finck buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; 143*c2c66affSColin Finck RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw); 144*c2c66affSColin Finck buf->st_atime = dw; 145*c2c66affSColin Finck RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); 146*c2c66affSColin Finck buf->st_mtime = buf->st_ctime = dw; 147*c2c66affSColin Finck buf->st_nlink = (short)hfi.nNumberOfLinks; 148*c2c66affSColin Finck } 149*c2c66affSColin Finck TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes, 150*c2c66affSColin Finck buf->st_mode); 151*c2c66affSColin Finck return 0; 152*c2c66affSColin Finck } 153*c2c66affSColin Finck 154*c2c66affSColin Finck #endif 155