7 #define ALL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
8 #define ALL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
9 #define ALL_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
12 #define TCHAR4 ULONGLONG
17 #define TCSIZE sizeof(_TCHAR)
18 #define TOULL(x) ((TCHAR4)(x))
20 #define EXE ((TOULL('e')<<(2*TCSIZE)) | (TOULL('x')<<TCSIZE) | (TOULL('e')))
21 #define BAT ((TOULL('b')<<(2*TCSIZE)) | (TOULL('a')<<TCSIZE) | (TOULL('t')))
22 #define CMD ((TOULL('c')<<(2*TCSIZE)) | (TOULL('m')<<TCSIZE) | (TOULL('d')))
23 #define COM ((TOULL('c')<<(2*TCSIZE)) | (TOULL('o')<<TCSIZE) | (TOULL('m')))
25 int CDECL
_tstat64(const _TCHAR
*path
, struct __stat64
*buf
)
28 WIN32_FILE_ATTRIBUTE_DATA hfi
;
29 unsigned short mode
= ALL_S_IREAD
;
32 TRACE(":file (%s) buf(%p)\n",path
,buf
);
34 if (!GetFileAttributesEx(path
, GetFileExInfoStandard
, &hfi
))
36 TRACE("failed (%d)\n",GetLastError());
37 _dosmaperr(ERROR_FILE_NOT_FOUND
);
41 memset(buf
,0,sizeof(struct __stat64
));
43 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
44 Bon 011120: This FIXME seems incorrect
45 Also a letter as first char isn't enough to be classified
48 if (isalpha((unsigned char)*path
)&& (*(path
+1)==':'))
49 buf
->st_dev
= buf
->st_rdev
= _totupper(*path
) - 'A'; /* drive num */
51 buf
->st_dev
= buf
->st_rdev
= _getdrive() - 1;
55 /* Dir, or regular file? */
56 if ((hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
57 (path
[plen
-1] == '\\'))
58 mode
|= (_S_IFDIR
| ALL_S_IEXEC
);
63 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
65 TCHAR4 ext
= _totlower(path
[plen
-1]) | (_totlower(path
[plen
-2]) << TCSIZE
) |
66 (_totlower(path
[plen
-3]) << (2*TCSIZE
));
67 if (ext
== EXE
|| ext
== BAT
|| ext
== CMD
|| ext
== COM
)
72 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
77 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
78 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
80 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
81 buf
->st_mtime
= buf
->st_ctime
= dw
;
82 TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf
->st_mode
,buf
->st_nlink
,
83 (long)(buf
->st_size
>> 32),(long)buf
->st_size
,
84 (long)buf
->st_atime
,(long)buf
->st_mtime
,(long)buf
->st_ctime
);
90 int CDECL
_fstat64(int fd
, struct __stat64
* buf
)
94 BY_HANDLE_FILE_INFORMATION hfi
;
95 HANDLE hand
= fdtoh(fd
);
97 TRACE(":fd (%d) stat (%p)\n",fd
,buf
);
98 if (hand
== INVALID_HANDLE_VALUE
)
103 WARN(":failed-NULL buf\n");
104 _dosmaperr(ERROR_INVALID_PARAMETER
);
108 memset(&hfi
, 0, sizeof(hfi
));
109 memset(buf
, 0, sizeof(struct __stat64
));
110 type
= GetFileType(hand
);
111 if (type
== FILE_TYPE_PIPE
)
113 buf
->st_dev
= buf
->st_rdev
= fd
;
114 buf
->st_mode
= _S_IFIFO
;
117 else if (type
== FILE_TYPE_CHAR
)
119 buf
->st_dev
= buf
->st_rdev
= fd
;
120 buf
->st_mode
= _S_IFCHR
;
123 else /* FILE_TYPE_DISK etc. */
125 if (!GetFileInformationByHandle(hand
, &hfi
))
127 WARN(":failed-last error (%d)\n",GetLastError());
128 _dosmaperr(ERROR_INVALID_PARAMETER
);
131 buf
->st_mode
= _S_IFREG
| ALL_S_IREAD
;
132 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
133 buf
->st_mode
|= ALL_S_IWRITE
;
134 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
135 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
137 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
138 buf
->st_mtime
= buf
->st_ctime
= dw
;
139 buf
->st_nlink
= (short)hfi
.nNumberOfLinks
;
141 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi
.dwFileAttributes
,