xref: /reactos/sdk/lib/crt/stdio/stat64.c (revision c8719ee8)
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