PostgreSQL Source Code  git master
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:73
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:221
#define MAXPGPATH
static pg_noinline void Size size
Definition: slab.c:607
const char * name
#define S_ISDIR(m)
Definition: win32_port.h:325
#define readlink(path, buf, size)
Definition: win32_port.h:236
#define S_IFLNK
Definition: win32_port.h:343
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:344
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 }
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 }

Referenced by fileinfo_to_stat().