1 /*-------------------------------------------------------------------------
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
11 * src/port/win32stat.c
13 *-------------------------------------------------------------------------
22 * Convert a FILETIME struct into a 64 bit time_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
)
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.
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 */
65 * Convert WIN32 file information (from a HANDLE) to a struct stat.
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());
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
);
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
);
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
);
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.
126 hFile
= pgwin32_open_handle(name
, O_RDONLY
, true);
127 if (hFile
== INVALID_HANDLE_VALUE
)
130 ret
= fileinfo_to_stat(hFile
, buf
);
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
)
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
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
;
170 return fileinfo_to_stat(hFile
, buf
);