xref: /reactos/sdk/lib/crt/stdio/stat64.c (revision c2c66aff)
1*c2c66affSColin Finck #include <precomp.h>
2*c2c66affSColin Finck #include <tchar.h>
3*c2c66affSColin Finck #include <direct.h>
4*c2c66affSColin Finck 
5*c2c66affSColin Finck HANDLE fdtoh(int fd);
6*c2c66affSColin Finck 
7*c2c66affSColin Finck #define ALL_S_IREAD  (_S_IREAD  | (_S_IREAD  >> 3) | (_S_IREAD  >> 6))
8*c2c66affSColin Finck #define ALL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
9*c2c66affSColin Finck #define ALL_S_IEXEC  (_S_IEXEC  | (_S_IEXEC  >> 3) | (_S_IEXEC  >> 6))
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #ifdef UNICODE
12*c2c66affSColin Finck #define TCHAR4 ULONGLONG
13*c2c66affSColin Finck #else
14*c2c66affSColin Finck #define TCHAR4 ULONG
15*c2c66affSColin Finck #endif
16*c2c66affSColin Finck 
17*c2c66affSColin Finck #define TCSIZE sizeof(_TCHAR)
18*c2c66affSColin Finck #define TOULL(x) ((TCHAR4)(x))
19*c2c66affSColin Finck 
20*c2c66affSColin Finck #define EXE ((TOULL('e')<<(2*TCSIZE)) | (TOULL('x')<<TCSIZE) | (TOULL('e')))
21*c2c66affSColin Finck #define BAT ((TOULL('b')<<(2*TCSIZE)) | (TOULL('a')<<TCSIZE) | (TOULL('t')))
22*c2c66affSColin Finck #define CMD ((TOULL('c')<<(2*TCSIZE)) | (TOULL('m')<<TCSIZE) | (TOULL('d')))
23*c2c66affSColin Finck #define COM ((TOULL('c')<<(2*TCSIZE)) | (TOULL('o')<<TCSIZE) | (TOULL('m')))
24*c2c66affSColin Finck 
25*c2c66affSColin Finck int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf)
26*c2c66affSColin Finck {
27*c2c66affSColin Finck   DWORD dw;
28*c2c66affSColin Finck   WIN32_FILE_ATTRIBUTE_DATA hfi;
29*c2c66affSColin Finck   unsigned short mode = ALL_S_IREAD;
30*c2c66affSColin Finck   int plen;
31*c2c66affSColin Finck 
32*c2c66affSColin Finck   TRACE(":file (%s) buf(%p)\n",path,buf);
33*c2c66affSColin Finck 
34*c2c66affSColin Finck   plen = _tcslen(path);
35*c2c66affSColin Finck   while (plen && path[plen-1]==' ')
36*c2c66affSColin Finck     plen--;
37*c2c66affSColin Finck 
38*c2c66affSColin Finck   if (plen && (plen<2 || path[plen-2]!=':') &&
39*c2c66affSColin Finck           (path[plen-1]==':' || path[plen-1]=='\\' || path[plen-1]=='/'))
40*c2c66affSColin Finck   {
41*c2c66affSColin Finck     *_errno() = ENOENT;
42*c2c66affSColin Finck     return -1;
43*c2c66affSColin Finck   }
44*c2c66affSColin Finck 
45*c2c66affSColin Finck   if (!GetFileAttributesEx(path, GetFileExInfoStandard, &hfi))
46*c2c66affSColin Finck   {
47*c2c66affSColin Finck       TRACE("failed (%d)\n",GetLastError());
48*c2c66affSColin Finck       *_errno() = ENOENT;
49*c2c66affSColin Finck       return -1;
50*c2c66affSColin Finck   }
51*c2c66affSColin Finck 
52*c2c66affSColin Finck   memset(buf,0,sizeof(struct __stat64));
53*c2c66affSColin Finck 
54*c2c66affSColin Finck   /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
55*c2c66affSColin Finck      Bon 011120: This FIXME seems incorrect
56*c2c66affSColin Finck                  Also a letter as first char isn't enough to be classified
57*c2c66affSColin Finck 		 as a drive letter
58*c2c66affSColin Finck   */
59*c2c66affSColin Finck   if (isalpha(*path)&& (*(path+1)==':'))
60*c2c66affSColin Finck     buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
61*c2c66affSColin Finck   else
62*c2c66affSColin Finck     buf->st_dev = buf->st_rdev = _getdrive() - 1;
63*c2c66affSColin Finck 
64*c2c66affSColin Finck   /* Dir, or regular file? */
65*c2c66affSColin Finck   if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
66*c2c66affSColin Finck     mode |= (_S_IFDIR | ALL_S_IEXEC);
67*c2c66affSColin Finck   else
68*c2c66affSColin Finck   {
69*c2c66affSColin Finck     mode |= _S_IFREG;
70*c2c66affSColin Finck     /* executable? */
71*c2c66affSColin Finck     if (plen > 6 && path[plen-4] == '.')  /* shortest exe: "\x.exe" */
72*c2c66affSColin Finck     {
73*c2c66affSColin Finck       unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) |
74*c2c66affSColin Finck                                  (tolower(path[plen-3]) << 16);
75*c2c66affSColin Finck       if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
76*c2c66affSColin Finck           mode |= ALL_S_IEXEC;
77*c2c66affSColin Finck     }
78*c2c66affSColin Finck   }
79*c2c66affSColin Finck 
80*c2c66affSColin Finck   if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
81*c2c66affSColin Finck     mode |= ALL_S_IWRITE;
82*c2c66affSColin Finck 
83*c2c66affSColin Finck   buf->st_mode  = mode;
84*c2c66affSColin Finck   buf->st_nlink = 1;
85*c2c66affSColin Finck   buf->st_size  = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
86*c2c66affSColin Finck   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
87*c2c66affSColin Finck   buf->st_atime = dw;
88*c2c66affSColin Finck   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
89*c2c66affSColin Finck   buf->st_mtime = buf->st_ctime = dw;
90*c2c66affSColin Finck   TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
91*c2c66affSColin Finck         (int)(buf->st_size >> 32),(int)buf->st_size,
92*c2c66affSColin Finck         (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
93*c2c66affSColin Finck   return 0;
94*c2c66affSColin Finck }
95*c2c66affSColin Finck 
96*c2c66affSColin Finck #ifndef _UNICODE
97*c2c66affSColin Finck 
98*c2c66affSColin Finck int CDECL _fstat64(int fd, struct __stat64* buf)
99*c2c66affSColin Finck {
100*c2c66affSColin Finck   DWORD dw;
101*c2c66affSColin Finck   DWORD type;
102*c2c66affSColin Finck   BY_HANDLE_FILE_INFORMATION hfi;
103*c2c66affSColin Finck   HANDLE hand = fdtoh(fd);
104*c2c66affSColin Finck 
105*c2c66affSColin Finck   TRACE(":fd (%d) stat (%p)\n",fd,buf);
106*c2c66affSColin Finck   if (hand == INVALID_HANDLE_VALUE)
107*c2c66affSColin Finck     return -1;
108*c2c66affSColin Finck 
109*c2c66affSColin Finck   if (!buf)
110*c2c66affSColin Finck   {
111*c2c66affSColin Finck     WARN(":failed-NULL buf\n");
112*c2c66affSColin Finck     _dosmaperr(ERROR_INVALID_PARAMETER);
113*c2c66affSColin Finck     return -1;
114*c2c66affSColin Finck   }
115*c2c66affSColin Finck 
116*c2c66affSColin Finck   memset(&hfi, 0, sizeof(hfi));
117*c2c66affSColin Finck   memset(buf, 0, sizeof(struct __stat64));
118*c2c66affSColin Finck   type = GetFileType(hand);
119*c2c66affSColin Finck   if (type == FILE_TYPE_PIPE)
120*c2c66affSColin Finck   {
121*c2c66affSColin Finck     buf->st_dev = buf->st_rdev = fd;
122*c2c66affSColin Finck     buf->st_mode = _S_IFIFO;
123*c2c66affSColin Finck     buf->st_nlink = 1;
124*c2c66affSColin Finck   }
125*c2c66affSColin Finck   else if (type == FILE_TYPE_CHAR)
126*c2c66affSColin Finck   {
127*c2c66affSColin Finck     buf->st_dev = buf->st_rdev = fd;
128*c2c66affSColin Finck     buf->st_mode = _S_IFCHR;
129*c2c66affSColin Finck     buf->st_nlink = 1;
130*c2c66affSColin Finck   }
131*c2c66affSColin Finck   else /* FILE_TYPE_DISK etc. */
132*c2c66affSColin Finck   {
133*c2c66affSColin Finck     if (!GetFileInformationByHandle(hand, &hfi))
134*c2c66affSColin Finck     {
135*c2c66affSColin Finck       WARN(":failed-last error (%d)\n",GetLastError());
136*c2c66affSColin Finck       _dosmaperr(ERROR_INVALID_PARAMETER);
137*c2c66affSColin Finck       return -1;
138*c2c66affSColin Finck     }
139*c2c66affSColin Finck     buf->st_mode = _S_IFREG | ALL_S_IREAD;
140*c2c66affSColin Finck     if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
141*c2c66affSColin Finck       buf->st_mode |= ALL_S_IWRITE;
142*c2c66affSColin Finck     buf->st_size  = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
143*c2c66affSColin Finck     RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
144*c2c66affSColin Finck     buf->st_atime = dw;
145*c2c66affSColin Finck     RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
146*c2c66affSColin Finck     buf->st_mtime = buf->st_ctime = dw;
147*c2c66affSColin Finck     buf->st_nlink = (short)hfi.nNumberOfLinks;
148*c2c66affSColin Finck   }
149*c2c66affSColin Finck   TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes,
150*c2c66affSColin Finck    buf->st_mode);
151*c2c66affSColin Finck   return 0;
152*c2c66affSColin Finck }
153*c2c66affSColin Finck 
154*c2c66affSColin Finck #endif
155