Update copyright for 2022
[pgsql.git] / src / port / win32stat.c
blobe03ed5f35cae142e2b05dec610a97369bdc453e8
1 /*-------------------------------------------------------------------------
3 * win32stat.c
4 * Replacements for <sys/stat.h> functions using GetFileInformationByHandle
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * src/port/win32stat.c
13 *-------------------------------------------------------------------------
16 #ifdef WIN32
18 #include "c.h"
19 #include <windows.h>
22 * Convert a FILETIME struct into a 64 bit time_t.
24 static __time64_t
25 filetime_to_time(const FILETIME *ft)
27 ULARGE_INTEGER unified_ft = {0};
28 static const uint64 EpochShift = UINT64CONST(116444736000000000);
30 unified_ft.LowPart = ft->dwLowDateTime;
31 unified_ft.HighPart = ft->dwHighDateTime;
33 if (unified_ft.QuadPart < EpochShift)
34 return -1;
36 unified_ft.QuadPart -= EpochShift;
37 unified_ft.QuadPart /= 10 * 1000 * 1000;
39 return unified_ft.QuadPart;
43 * Convert WIN32 file attributes to a Unix-style mode.
45 * Only owner permissions are set.
47 static unsigned short
48 fileattr_to_unixmode(int attr)
50 unsigned short uxmode = 0;
52 uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_DIRECTORY) ?
53 (_S_IFDIR) : (_S_IFREG));
55 uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_READONLY) ?
56 (_S_IREAD) : (_S_IREAD | _S_IWRITE));
58 /* there is no need to simulate _S_IEXEC using CMD's PATHEXT extensions */
59 uxmode |= _S_IEXEC;
61 return uxmode;
65 * Convert WIN32 file information (from a HANDLE) to a struct stat.
67 static int
68 fileinfo_to_stat(HANDLE hFile, struct stat *buf)
70 BY_HANDLE_FILE_INFORMATION fiData;
72 memset(buf, 0, sizeof(*buf));
75 * GetFileInformationByHandle minimum supported version: Windows XP and
76 * Windows Server 2003, so it exists everywhere we care about.
78 if (!GetFileInformationByHandle(hFile, &fiData))
80 _dosmaperr(GetLastError());
81 return -1;
84 if (fiData.ftLastWriteTime.dwLowDateTime ||
85 fiData.ftLastWriteTime.dwHighDateTime)
86 buf->st_mtime = filetime_to_time(&fiData.ftLastWriteTime);
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;
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;
100 buf->st_mode = fileattr_to_unixmode(fiData.dwFileAttributes);
101 buf->st_nlink = fiData.nNumberOfLinks;
103 buf->st_size = ((((uint64) fiData.nFileSizeHigh) << 32) |
104 fiData.nFileSizeLow);
106 return 0;
110 * Windows implementation of stat().
112 * This currently also implements lstat(), though perhaps that should change.
115 _pgstat64(const char *name, struct stat *buf)
118 * Our open wrapper will report STATUS_DELETE_PENDING as ENOENT. We
119 * request FILE_FLAG_BACKUP_SEMANTICS so that we can open directories too,
120 * for limited purposes. We use the private handle-based version, so we
121 * don't risk running out of fds.
123 HANDLE hFile;
124 int ret;
126 hFile = pgwin32_open_handle(name, O_RDONLY, true);
127 if (hFile == INVALID_HANDLE_VALUE)
128 return -1;
130 ret = fileinfo_to_stat(hFile, buf);
132 CloseHandle(hFile);
133 return ret;
137 * Windows implementation of fstat().
140 _pgfstat64(int fileno, struct stat *buf)
142 HANDLE hFile = (HANDLE) _get_osfhandle(fileno);
143 BY_HANDLE_FILE_INFORMATION fiData;
145 if (hFile == INVALID_HANDLE_VALUE || buf == NULL)
147 errno = EINVAL;
148 return -1;
152 * Check if the fileno is a data stream. If so, unless it has been
153 * redirected to a file, getting information through its HANDLE will fail,
154 * so emulate its stat information in the most appropriate way and return
155 * it instead.
157 if ((fileno == _fileno(stdin) ||
158 fileno == _fileno(stdout) ||
159 fileno == _fileno(stderr)) &&
160 !GetFileInformationByHandle(hFile, &fiData))
162 memset(buf, 0, sizeof(*buf));
163 buf->st_mode = _S_IFCHR;
164 buf->st_dev = fileno;
165 buf->st_rdev = fileno;
166 buf->st_nlink = 1;
167 return 0;
170 return fileinfo_to_stat(hFile, buf);
173 #endif /* WIN32 */