2 #include "wine/unicode.h"
16 /* for stat mode, permissions apply to all,owner and group */
17 #define ALL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
18 #define ALL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
19 #define ALL_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
21 #define EXE ('e' << 16 | 'x' << 8 | 'e')
22 #define BAT ('b' << 16 | 'a' << 8 | 't')
23 #define CMD ('c' << 16 | 'm' << 8 | 'd')
24 #define COM ('c' << 16 | 'o' << 8 | 'm')
26 #define TOUL(x) (ULONGLONG)(x)
27 #define WCEXE (TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e'))
28 #define WCBAT (TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t'))
29 #define WCCMD (TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d'))
30 #define WCCOM (TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m'))
33 void stat64_to_stati64(const struct __stat64
*buf64
, struct _stati64
*buf
);
37 //int _tstati64(const TCHAR* path, struct _stati64 * buf)
40 // struct __stat64 buf64;
42 // ret = _tstat64(path, &buf64);
44 // stat64_to_stati64(&buf64, buf);
52 int CDECL
_tstat64(const _TCHAR
*path
, struct _stat64
*buf
)
54 int CDECL
_tstat64i32(const _TCHAR
*path
, struct _stat64i32
*buf
)
58 WIN32_FILE_ATTRIBUTE_DATA hfi
;
59 unsigned short mode
= ALL_S_IREAD
;
62 TRACE(":file (%s) buf(%p)\n",path
,buf
);
64 if (!GetFileAttributesEx(path
, GetFileExInfoStandard
, &hfi
))
66 TRACE("failed (%d)\n",GetLastError());
67 __set_errno(ERROR_FILE_NOT_FOUND
);
71 memset(buf
,0,sizeof(struct __stat64
));
73 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
74 Bon 011120: This FIXME seems incorrect
75 Also a letter as first char isn't enough to be classified
79 if (isalpha(*path
)&& (*(path
+1)==':'))
80 buf
->st_dev
= buf
->st_rdev
= toupper(*path
) - 'A'; /* drive num */
83 buf
->st_dev
= buf
->st_rdev
= toupperW(*path
- 'A'); /* drive num */
86 buf
->st_dev
= buf
->st_rdev
= _getdrive() - 1;
94 /* Dir, or regular file? */
95 if ((hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
96 (path
[plen
-1] == '\\'))
97 mode
|= (_S_IFDIR
| ALL_S_IEXEC
);
102 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
105 unsigned int ext
= tolower(path
[plen
-1]) | (tolower(path
[plen
-2]) << 8) |
106 (tolower(path
[plen
-3]) << 16);
107 if (ext
== EXE
|| ext
== BAT
|| ext
== CMD
|| ext
== COM
)
110 ULONGLONG ext
= tolowerW(path
[plen
-1]) | (tolowerW(path
[plen
-2]) << 16) |
111 ((ULONGLONG
)tolowerW(path
[plen
-3]) << 32);
112 if (ext
== WCEXE
|| ext
== WCBAT
|| ext
== WCCMD
|| ext
== WCCOM
)
118 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
119 mode
|= ALL_S_IWRITE
;
124 buf
->st_size
= buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
126 buf
->st_size
= hfi
.nFileSizeLow
;
128 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
130 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
131 buf
->st_mtime
= buf
->st_ctime
= dw
;
132 TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf
->st_mode
,buf
->st_nlink
,
133 (long)(buf
->st_size
>> 16),(long)buf
->st_size
,
134 (long)buf
->st_atime
,(long)buf
->st_mtime
,(long)buf
->st_ctime
);
138 /*********************************************************************
142 int CDECL
_tstat32i64(const _TCHAR
*path
,struct _stat32i64
*buf
)
144 int CDECL
_tstat32(const _TCHAR
*path
,struct _stat32
*buf
)
148 WIN32_FILE_ATTRIBUTE_DATA hfi
;
149 unsigned short mode
= ALL_S_IREAD
;
152 TRACE(":file (%s) buf(%p)\n",path
,buf
);
154 if (!GetFileAttributesEx(path
, GetFileExInfoStandard
, &hfi
))
156 TRACE("failed (%d)\n",GetLastError());
157 __set_errno(ERROR_FILE_NOT_FOUND
);
161 memset(buf
,0,sizeof(*buf
));
163 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
164 Bon 011120: This FIXME seems incorrect
165 Also a letter as first char isn't enough to be classified
169 if (isalpha(*path
)&& (*(path
+1)==':'))
170 buf
->st_dev
= buf
->st_rdev
= toupper(*path
) - 'A'; /* drive num */
173 buf
->st_dev
= buf
->st_rdev
= toupperW(*path
- 'A'); /* drive num */
176 buf
->st_dev
= buf
->st_rdev
= _getdrive() - 1;
181 plen
= strlenW(path
);
184 /* Dir, or regular file? */
185 if ((hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
186 (path
[plen
-1] == '\\'))
187 mode
|= (_S_IFDIR
| ALL_S_IEXEC
);
192 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
195 unsigned int ext
= tolower(path
[plen
-1]) | (tolower(path
[plen
-2]) << 8) |
196 (tolower(path
[plen
-3]) << 16);
197 if (ext
== EXE
|| ext
== BAT
|| ext
== CMD
|| ext
== COM
)
200 ULONGLONG ext
= tolowerW(path
[plen
-1]) | (tolowerW(path
[plen
-2]) << 16) |
201 ((ULONGLONG
)tolowerW(path
[plen
-3]) << 32);
202 if (ext
== WCEXE
|| ext
== WCBAT
|| ext
== WCCMD
|| ext
== WCCOM
)
208 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
209 mode
|= ALL_S_IWRITE
;
214 buf
->st_size
= ((__int32
)hfi
.nFileSizeHigh
<< 16) + hfi
.nFileSizeLow
;
216 buf
->st_size
= hfi
.nFileSizeLow
;
218 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
220 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
221 buf
->st_mtime
= buf
->st_ctime
= dw
;
222 TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf
->st_mode
,buf
->st_nlink
,
223 (long)(buf
->st_size
>> 16),(long)buf
->st_size
,
224 (long)buf
->st_atime
,(long)buf
->st_mtime
,(long)buf
->st_ctime
);
228 #ifndef _UNICODE //No wide versions needed
231 int CDECL
_fstat64(int fd
, struct _stat64
* buf
)
233 int CDECL
_fstat64i32(int fd
, struct _stat64i32
* buf
)
238 BY_HANDLE_FILE_INFORMATION hfi
;
239 HANDLE hand
= fdtoh(fd
);
241 TRACE(":fd (%d) stat (%p)\n",fd
,buf
);
242 if (hand
== INVALID_HANDLE_VALUE
)
247 WARN(":failed-NULL buf\n");
248 __set_errno(ERROR_INVALID_PARAMETER
);
252 memset(&hfi
, 0, sizeof(hfi
));
253 memset(buf
, 0, sizeof(struct __stat64
));
254 type
= GetFileType(hand
);
255 if (type
== FILE_TYPE_PIPE
)
257 buf
->st_dev
= buf
->st_rdev
= fd
;
258 buf
->st_mode
= S_IFIFO
;
261 else if (type
== FILE_TYPE_CHAR
)
263 buf
->st_dev
= buf
->st_rdev
= fd
;
264 buf
->st_mode
= S_IFCHR
;
267 else /* FILE_TYPE_DISK etc. */
269 if (!GetFileInformationByHandle(hand
, &hfi
))
271 WARN(":failed-last error (%d)\n",GetLastError());
272 __set_errno(ERROR_INVALID_PARAMETER
);
275 buf
->st_mode
= S_IFREG
| S_IREAD
;
276 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
277 buf
->st_mode
|= S_IWRITE
;
278 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
279 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
281 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
282 buf
->st_mtime
= buf
->st_ctime
= dw
;
283 buf
->st_nlink
= hfi
.nNumberOfLinks
;
285 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi
.dwFileAttributes
,
290 /*********************************************************************
294 int CDECL
_fstat32(int fd
, struct _stat32
* buf
)
296 int CDECL
_fstat32i64(int fd
, struct _stat32i64
* buf
)
301 BY_HANDLE_FILE_INFORMATION hfi
;
302 HANDLE hand
= fdtoh(fd
);
304 TRACE(":fd (%d) stat (%p)\n",fd
,buf
);
305 if (hand
== INVALID_HANDLE_VALUE
)
310 WARN(":failed-NULL buf\n");
311 __set_errno(ERROR_INVALID_PARAMETER
);
315 memset(&hfi
, 0, sizeof(hfi
));
316 memset(buf
, 0, sizeof(struct _stat32
));
317 type
= GetFileType(hand
);
318 if (type
== FILE_TYPE_PIPE
)
320 buf
->st_dev
= buf
->st_rdev
= fd
;
321 buf
->st_mode
= S_IFIFO
;
324 else if (type
== FILE_TYPE_CHAR
)
326 buf
->st_dev
= buf
->st_rdev
= fd
;
327 buf
->st_mode
= S_IFCHR
;
330 else /* FILE_TYPE_DISK etc. */
332 if (!GetFileInformationByHandle(hand
, &hfi
))
334 WARN(":failed-last error (%d)\n",GetLastError());
335 __set_errno(ERROR_INVALID_PARAMETER
);
338 buf
->st_mode
= S_IFREG
| S_IREAD
;
339 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
340 buf
->st_mode
|= S_IWRITE
;
341 buf
->st_size
= ((__int32
)hfi
.nFileSizeHigh
<< 16) + hfi
.nFileSizeLow
;
342 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
344 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
345 buf
->st_mtime
= buf
->st_ctime
= dw
;
346 buf
->st_nlink
= hfi
.nNumberOfLinks
;
348 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi
.dwFileAttributes
,