PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
win32stat.c File Reference
#include "c.h"
#include "port/win32ntdll.h"
#include <windows.h>
Include dependency graph for win32stat.c:

Go to the source code of this file.

Functions

static __time64_t filetime_to_time (const FILETIME *ft)
 
static unsigned short fileattr_to_unixmode (int attr)
 
static int fileinfo_to_stat (HANDLE hFile, struct stat *buf)
 
int _pglstat64 (const char *name, struct stat *buf)
 
int _pgstat64 (const char *name, struct stat *buf)
 
int _pgfstat64 (int fileno, struct stat *buf)
 

Function Documentation

◆ _pgfstat64()

int _pgfstat64 ( int  fileno,
struct stat buf 
)

Definition at line 255 of file win32stat.c.

256{
257 HANDLE hFile = (HANDLE) _get_osfhandle(fileno);
258 DWORD fileType = FILE_TYPE_UNKNOWN;
259 unsigned short st_mode;
260
261 if (buf == NULL)
262 {
263 errno = EINVAL;
264 return -1;
265 }
266
267 fileType = pgwin32_get_file_type(hFile);
268 if (errno != 0)
269 return -1;
270
271 switch (fileType)
272 {
273 /* The specified file is a disk file */
274 case FILE_TYPE_DISK:
275 return fileinfo_to_stat(hFile, buf);
276
277 /*
278 * The specified file is a socket, a named pipe, or an anonymous
279 * pipe.
280 */
281 case FILE_TYPE_PIPE:
282 st_mode = _S_IFIFO;
283 break;
284 /* The specified file is a character file */
285 case FILE_TYPE_CHAR:
286 st_mode = _S_IFCHR;
287 break;
288 /* Unused flag and unknown file type */
289 case FILE_TYPE_REMOTE:
290 case FILE_TYPE_UNKNOWN:
291 default:
292 errno = EINVAL;
293 return -1;
294 }
295
296 memset(buf, 0, sizeof(*buf));
297 buf->st_mode = st_mode;
298 buf->st_dev = fileno;
299 buf->st_rdev = fileno;
300 buf->st_nlink = 1;
301 return 0;
302}
static char * buf
Definition: pg_test_fsync.c:72
DWORD pgwin32_get_file_type(HANDLE hFile)
Definition: win32common.c:31
static int fileinfo_to_stat(HANDLE hFile, struct stat *buf)
Definition: win32stat.c:68

References buf, fileinfo_to_stat(), and pgwin32_get_file_type().

◆ _pglstat64()

int _pglstat64 ( const char *  name,
struct stat buf 
)

Definition at line 113 of file win32stat.c.

114{
115 /*
116 * Our open wrapper will report STATUS_DELETE_PENDING as ENOENT. We
117 * request FILE_FLAG_BACKUP_SEMANTICS so that we can open directories too,
118 * for limited purposes. We use the private handle-based version, so we
119 * don't risk running out of fds.
120 */
121 HANDLE hFile;
122 int ret;
123
124 hFile = pgwin32_open_handle(name, O_RDONLY, true);
125 if (hFile == INVALID_HANDLE_VALUE)
126 {
127 if (errno == ENOENT)
128 {
129 /*
130 * If it's a junction point pointing to a non-existent path, we'll
131 * have ENOENT here (because pgwin32_open_handle does not use
132 * FILE_FLAG_OPEN_REPARSE_POINT). In that case, we'll try again
133 * with readlink() below, which will distinguish true ENOENT from
134 * pseudo-symlink.
135 */
136 memset(buf, 0, sizeof(*buf));
137 ret = 0;
138 }
139 else
140 return -1;
141 }
142 else
143 ret = fileinfo_to_stat(hFile, buf);
144
145 /*
146 * Junction points appear as directories to fileinfo_to_stat(), so we'll
147 * need to do a bit more work to distinguish them.
148 */
149 if ((ret == 0 && S_ISDIR(buf->st_mode)) || hFile == INVALID_HANDLE_VALUE)
150 {
151 char next[MAXPGPATH];
152 ssize_t size;
153
154 /*
155 * POSIX says we need to put the length of the target path into
156 * st_size. Use readlink() to get it, or learn that this is not a
157 * junction point.
158 */
159 size = readlink(name, next, sizeof(next));
160 if (size < 0)
161 {
162 if (errno == EACCES &&
163 pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
164 {
165 /* Unlinked underneath us. */
166 errno = ENOENT;
167 ret = -1;
168 }
169 else if (errno == EINVAL)
170 {
171 /* It's not a junction point, nothing to do. */
172 }
173 else
174 {
175 /* Some other failure. */
176 ret = -1;
177 }
178 }
179 else
180 {
181 /* It's a junction point, so report it as a symlink. */
182 buf->st_mode &= ~S_IFDIR;
183 buf->st_mode |= S_IFLNK;
184 buf->st_size = size;
185 ret = 0;
186 }
187 }
188
189 if (hFile != INVALID_HANDLE_VALUE)
190 CloseHandle(hFile);
191 return ret;
192}
static int32 next
Definition: blutils.c:219
#define MAXPGPATH
static pg_noinline void Size size
Definition: slab.c:607
const char * name
#define S_ISDIR(m)
Definition: win32_port.h:315
#define readlink(path, buf, size)
Definition: win32_port.h:226
#define S_IFLNK
Definition: win32_port.h:333
PGDLLIMPORT RtlGetLastNtStatus_t pg_RtlGetLastNtStatus
Definition: win32ntdll.c:20

References buf, fileinfo_to_stat(), MAXPGPATH, name, next, pg_RtlGetLastNtStatus, readlink, S_IFLNK, S_ISDIR, and size.

Referenced by _pgstat64().

◆ _pgstat64()

int _pgstat64 ( const char *  name,
struct stat buf 
)

Definition at line 198 of file win32stat.c.

199{
200 int loops = 0;
201 int ret;
202 char curr[MAXPGPATH];
203
204 ret = _pglstat64(name, buf);
205
206 strlcpy(curr, name, MAXPGPATH);
207
208 /* Do we need to follow a symlink (junction point)? */
209 while (ret == 0 && S_ISLNK(buf->st_mode))
210 {
211 char next[MAXPGPATH];
212 ssize_t size;
213
214 if (++loops > 8)
215 {
216 errno = ELOOP;
217 return -1;
218 }
219
220 /*
221 * _pglstat64() already called readlink() once to be able to fill in
222 * st_size, and now we need to do it again to get the path to follow.
223 * That could be optimized, but stat() on symlinks is probably rare
224 * and this way is simple.
225 */
226 size = readlink(curr, next, sizeof(next));
227 if (size < 0)
228 {
229 if (errno == EACCES &&
230 pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
231 {
232 /* Unlinked underneath us. */
233 errno = ENOENT;
234 }
235 return -1;
236 }
237 if (size >= sizeof(next))
238 {
239 errno = ENAMETOOLONG;
240 return -1;
241 }
242 next[size] = 0;
243
244 ret = _pglstat64(next, buf);
245 strcpy(curr, next);
246 }
247
248 return ret;
249}
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define S_ISLNK(m)
Definition: win32_port.h:334
int _pglstat64(const char *name, struct stat *buf)
Definition: win32stat.c:113

References _pglstat64(), buf, MAXPGPATH, name, next, pg_RtlGetLastNtStatus, readlink, S_ISLNK, size, and strlcpy().

◆ fileattr_to_unixmode()

static unsigned short fileattr_to_unixmode ( int  attr)
static

Definition at line 48 of file win32stat.c.

49{
50 unsigned short uxmode = 0;
51
52 uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_DIRECTORY) ?
53 (_S_IFDIR) : (_S_IFREG));
54
55 uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_READONLY) ?
56 (_S_IREAD) : (_S_IREAD | _S_IWRITE));
57
58 /* there is no need to simulate _S_IEXEC using CMD's PATHEXT extensions */
59 uxmode |= _S_IEXEC;
60
61 return uxmode;
62}

Referenced by fileinfo_to_stat().

◆ fileinfo_to_stat()

static int fileinfo_to_stat ( HANDLE  hFile,
struct stat buf 
)
static

Definition at line 68 of file win32stat.c.

69{
70 BY_HANDLE_FILE_INFORMATION fiData;
71
72 memset(buf, 0, sizeof(*buf));
73
74 /*
75 * GetFileInformationByHandle minimum supported version: Windows XP and
76 * Windows Server 2003, so it exists everywhere we care about.
77 */
78 if (!GetFileInformationByHandle(hFile, &fiData))
79 {
80 _dosmaperr(GetLastError());
81 return -1;
82 }
83
84 if (fiData.ftLastWriteTime.dwLowDateTime ||
85 fiData.ftLastWriteTime.dwHighDateTime)
86 buf->st_mtime = filetime_to_time(&fiData.ftLastWriteTime);
87
88 if (fiData.ftLastAccessTime.dwLowDateTime ||
89 fiData.ftLastAccessTime.dwHighDateTime)
90 buf->st_atime = filetime_to_time(&fiData.ftLastAccessTime);
91 else
92 buf->st_atime = buf->st_mtime;
93
94 if (fiData.ftCreationTime.dwLowDateTime ||
95 fiData.ftCreationTime.dwHighDateTime)
96 buf->st_ctime = filetime_to_time(&fiData.ftCreationTime);
97 else
98 buf->st_ctime = buf->st_mtime;
99
100 buf->st_mode = fileattr_to_unixmode(fiData.dwFileAttributes);
101 buf->st_nlink = fiData.nNumberOfLinks;
102
103 buf->st_size = ((((uint64) fiData.nFileSizeHigh) << 32) |
104 fiData.nFileSizeLow);
105
106 return 0;
107}
uint64_t uint64
Definition: c.h:489
void _dosmaperr(unsigned long)
Definition: win32error.c:177
static __time64_t filetime_to_time(const FILETIME *ft)
Definition: win32stat.c:25
static unsigned short fileattr_to_unixmode(int attr)
Definition: win32stat.c:48

References _dosmaperr(), buf, fileattr_to_unixmode(), and filetime_to_time().

Referenced by _pgfstat64(), and _pglstat64().

◆ filetime_to_time()

static __time64_t filetime_to_time ( const FILETIME *  ft)
static

Definition at line 25 of file win32stat.c.

26{
27 ULARGE_INTEGER unified_ft = {0};
28 static const uint64 EpochShift = UINT64CONST(116444736000000000);
29
30 unified_ft.LowPart = ft->dwLowDateTime;
31 unified_ft.HighPart = ft->dwHighDateTime;
32
33 if (unified_ft.QuadPart < EpochShift)
34 return -1;
35
36 unified_ft.QuadPart -= EpochShift;
37 unified_ft.QuadPart /= 10 * 1000 * 1000;
38
39 return unified_ft.QuadPart;
40}
#define UINT64CONST(x)
Definition: c.h:503

References UINT64CONST.

Referenced by fileinfo_to_stat().