#include #include #include #include inline ioinfo* get_ioinfo(int fd); inline void release_ioinfo(ioinfo *info); #define ALL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)) #define ALL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) #define ALL_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)) #ifdef UNICODE #define TCHAR4 ULONGLONG #else #define TCHAR4 ULONG #endif #define TCSIZE_BITS (sizeof(_TCHAR)*8) #define EXE (((TCHAR4)('e')<<(2*TCSIZE_BITS)) | ((TCHAR4)('x')<st_dev = buf->st_rdev = _totupper(*path) - __T('A'); /* drive num */ else buf->st_dev = buf->st_rdev = _getdrive() - 1; /* Dir, or regular file? */ if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) mode |= (_S_IFDIR | ALL_S_IEXEC); else { mode |= _S_IFREG; /* executable? */ if (plen > 6 && path[plen-4] == __T('.')) /* shortest exe: "\x.exe" */ { TCHAR4 ext = (TCHAR4)_totlower(path[plen-1]) | ((TCHAR4)_totlower(path[plen-2]) << TCSIZE_BITS) | ((TCHAR4)_totlower(path[plen-3]) << 2*TCSIZE_BITS); if (ext == EXE || ext == BAT || ext == CMD || ext == COM) mode |= ALL_S_IEXEC; } } if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) mode |= ALL_S_IWRITE; buf->st_mode = mode; buf->st_nlink = 1; buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw); buf->st_atime = dw; RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); buf->st_mtime = buf->st_ctime = dw; TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink, (int)(buf->st_size >> 32),(int)buf->st_size, (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime); return 0; } #ifndef _UNICODE int CDECL _fstat64(int fd, struct __stat64* buf) { ioinfo *info = get_ioinfo(fd); DWORD dw; DWORD type; BY_HANDLE_FILE_INFORMATION hfi; TRACE(":fd (%d) stat (%p)\n", fd, buf); if (info->handle == INVALID_HANDLE_VALUE) { release_ioinfo(info); return -1; } if (!buf) { WARN(":failed-NULL buf\n"); _dosmaperr(ERROR_INVALID_PARAMETER); release_ioinfo(info); return -1; } memset(&hfi, 0, sizeof(hfi)); memset(buf, 0, sizeof(struct __stat64)); type = GetFileType(info->handle); if (type == FILE_TYPE_PIPE) { buf->st_dev = buf->st_rdev = fd; buf->st_mode = _S_IFIFO; buf->st_nlink = 1; } else if (type == FILE_TYPE_CHAR) { buf->st_dev = buf->st_rdev = fd; buf->st_mode = _S_IFCHR; buf->st_nlink = 1; } else /* FILE_TYPE_DISK etc. */ { if (!GetFileInformationByHandle(info->handle, &hfi)) { WARN(":failed-last error (%d)\n",GetLastError()); _dosmaperr(ERROR_INVALID_PARAMETER); release_ioinfo(info); return -1; } buf->st_mode = _S_IFREG | ALL_S_IREAD; if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) buf->st_mode |= ALL_S_IWRITE; buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw); buf->st_atime = dw; RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); buf->st_mtime = buf->st_ctime = dw; buf->st_nlink = (short)hfi.nNumberOfLinks; } TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes, buf->st_mode); release_ioinfo(info); return 0; } #endif