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