1 /*-------------------------------------------------------------------------
4 * Win32 open() replacement
7 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
11 *-------------------------------------------------------------------------
19 #include "postgres_fe.h"
22 #include "port/win32ntdll.h"
29 openFlagsToCreateFileFlags(int openFlags
)
31 switch (openFlags
& (O_CREAT
| O_TRUNC
| O_EXCL
))
33 /* O_EXCL is meaningless without O_CREAT */
41 /* O_EXCL is meaningless without O_CREAT */
43 case O_TRUNC
| O_EXCL
:
44 return TRUNCATE_EXISTING
;
46 case O_CREAT
| O_TRUNC
:
49 /* O_TRUNC is meaningless with O_CREAT */
50 case O_CREAT
| O_EXCL
:
51 case O_CREAT
| O_TRUNC
| O_EXCL
:
55 /* will never get here */
60 * Internal function used by pgwin32_open() and _pgstat64(). When
61 * backup_semantics is true, directories may be opened (for limited uses). On
62 * failure, INVALID_HANDLE_VALUE is returned and errno is set.
65 pgwin32_open_handle(const char *fileName
, int fileFlags
, bool backup_semantics
)
68 SECURITY_ATTRIBUTES sa
;
71 if (initialize_ntdll() < 0)
72 return INVALID_HANDLE_VALUE
;
74 /* Check that we can handle the request */
75 assert((fileFlags
& ((O_RDONLY
| O_WRONLY
| O_RDWR
) | O_APPEND
|
76 (O_RANDOM
| O_SEQUENTIAL
| O_TEMPORARY
) |
77 _O_SHORT_LIVED
| O_DSYNC
| O_DIRECT
|
78 (O_CREAT
| O_TRUNC
| O_EXCL
) | (O_TEXT
| O_BINARY
))) == fileFlags
);
80 sa
.nLength
= sizeof(sa
);
81 sa
.bInheritHandle
= TRUE
;
82 sa
.lpSecurityDescriptor
= NULL
;
84 while ((h
= CreateFile(fileName
,
85 /* cannot use O_RDONLY, as it == 0 */
86 (fileFlags
& O_RDWR
) ? (GENERIC_WRITE
| GENERIC_READ
) :
87 ((fileFlags
& O_WRONLY
) ? GENERIC_WRITE
: GENERIC_READ
),
88 /* These flags allow concurrent rename/unlink */
89 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
),
91 openFlagsToCreateFileFlags(fileFlags
),
92 FILE_ATTRIBUTE_NORMAL
|
93 (backup_semantics
? FILE_FLAG_BACKUP_SEMANTICS
: 0) |
94 ((fileFlags
& O_RANDOM
) ? FILE_FLAG_RANDOM_ACCESS
: 0) |
95 ((fileFlags
& O_SEQUENTIAL
) ? FILE_FLAG_SEQUENTIAL_SCAN
: 0) |
96 ((fileFlags
& _O_SHORT_LIVED
) ? FILE_ATTRIBUTE_TEMPORARY
: 0) |
97 ((fileFlags
& O_TEMPORARY
) ? FILE_FLAG_DELETE_ON_CLOSE
: 0) |
98 ((fileFlags
& O_DIRECT
) ? FILE_FLAG_NO_BUFFERING
: 0) |
99 ((fileFlags
& O_DSYNC
) ? FILE_FLAG_WRITE_THROUGH
: 0),
100 NULL
)) == INVALID_HANDLE_VALUE
)
103 * Sharing violation or locking error can indicate antivirus, backup
104 * or similar software that's locking the file. Wait a bit and try
105 * again, giving up after 30 seconds.
107 DWORD err
= GetLastError();
109 if (err
== ERROR_SHARING_VIOLATION
||
110 err
== ERROR_LOCK_VIOLATION
)
115 (errmsg("could not open file \"%s\": %s", fileName
,
116 (err
== ERROR_SHARING_VIOLATION
) ? _("sharing violation") : _("lock violation")),
117 errdetail("Continuing to retry for 30 seconds."),
118 errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
130 * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet
131 * gone (Windows NT status code is STATUS_DELETE_PENDING). In that
132 * case, we'd better ask for the NT status too so we can translate it
133 * to a more Unix-like error. We hope that nothing clobbers the NT
134 * status in between the internal NtCreateFile() call and CreateFile()
137 * If there's no O_CREAT flag, then we'll pretend the file is
138 * invisible. With O_CREAT, we have no choice but to report that
139 * there's a file in the way (which wouldn't happen on Unix).
141 if (err
== ERROR_ACCESS_DENIED
&&
142 pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING
)
144 if (fileFlags
& O_CREAT
)
145 err
= ERROR_FILE_EXISTS
;
147 err
= ERROR_FILE_NOT_FOUND
;
151 return INVALID_HANDLE_VALUE
;
158 pgwin32_open(const char *fileName
, int fileFlags
,...)
163 h
= pgwin32_open_handle(fileName
, fileFlags
, false);
164 if (h
== INVALID_HANDLE_VALUE
)
170 * Since PostgreSQL 12, those concurrent-safe versions of open() and
171 * fopen() can be used by frontends, having as side-effect to switch the
172 * file-translation mode from O_TEXT to O_BINARY if none is specified.
173 * Caller may want to enforce the binary or text mode, but if nothing is
174 * defined make sure that the default mode maps with what versions older
175 * than 12 have been doing.
177 if ((fileFlags
& O_BINARY
) == 0)
181 /* _open_osfhandle will, on error, set errno accordingly */
182 if ((fd
= _open_osfhandle((intptr_t) h
, fileFlags
& O_APPEND
)) < 0)
183 CloseHandle(h
); /* will not affect errno */
184 else if (fileFlags
& (O_TEXT
| O_BINARY
) &&
185 _setmode(fd
, fileFlags
& (O_TEXT
| O_BINARY
)) < 0)
195 pgwin32_fopen(const char *fileName
, const char *mode
)
200 if (strstr(mode
, "r+"))
202 else if (strchr(mode
, 'r'))
203 openmode
|= O_RDONLY
;
204 if (strstr(mode
, "w+"))
205 openmode
|= O_RDWR
| O_CREAT
| O_TRUNC
;
206 else if (strchr(mode
, 'w'))
207 openmode
|= O_WRONLY
| O_CREAT
| O_TRUNC
;
208 if (strchr(mode
, 'a'))
209 openmode
|= O_WRONLY
| O_CREAT
| O_APPEND
;
211 if (strchr(mode
, 'b'))
212 openmode
|= O_BINARY
;
213 if (strchr(mode
, 't'))
216 fd
= pgwin32_open(fileName
, openmode
);
219 return _fdopen(fd
, mode
);